//-------------------------------------------------------------------------
        public void line3(line_parameters lp,
                          int sx, int sy, int ex, int ey)
        {
            if (m_clipping)
            {
                int  x1    = lp.x1;
                int  y1    = lp.y1;
                int  x2    = lp.x2;
                int  y2    = lp.y2;
                uint flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box);
                int  start = m_start;
                if ((flags & 4) == 0)
                {
                    if (flags)
                    {
                        line_parameters lp2(x1, y1, x2, y2,
                                            uround(calc_distance(x1, y1, x2, y2)));

                        if (flags & 1)
                        {
                            m_start += uround(calc_distance(lp.x1, lp.y1, x1, y1) / m_scale_x);
                            sx       = x1 + (y2 - y1);
                            sy       = y1 - (x2 - x1);
                        }
                        else
                        {
                            while (abs(sx - lp.x1) + abs(sy - lp.y1) > lp2.len)
                            {
                                sx = (lp.x1 + sx) >> 1;
                                sy = (lp.y1 + sy) >> 1;
                            }
                        }
                        if (flags & 2)
                        {
                            ex = x2 + (y2 - y1);
                            ey = y2 - (x2 - x1);
                        }
                        else
                        {
                            while (abs(ex - lp.x2) + abs(ey - lp.y2) > lp2.len)
                            {
                                ex = (lp.x2 + ex) >> 1;
                                ey = (lp.y2 + ey) >> 1;
                            }
                        }
                        line3_no_clip(lp2, sx, sy, ex, ey);
                    }
                    else
                    {
                        line3_no_clip(lp, sx, sy, ex, ey);
                    }
                }
                m_start = start + uround(lp.len / m_scale_x);
            }
            else
            {
                line3_no_clip(lp, sx, sy, ex, ey);
            }
        }
        /*
         * //-------------------------------------------------------------------------
         * public void semidot(Cmp, int, int, int, int)
         * {
         * }
         *
         * //-------------------------------------------------------------------------
         * public void pie(int, int, int, int, int, int)
         * {
         * }
         *
         * //-------------------------------------------------------------------------
         * public void line0(line_parameters)
         * {
         * }
         *
         * //-------------------------------------------------------------------------
         * public void line1(line_parameters, int, int)
         * {
         * }
         *
         * //-------------------------------------------------------------------------
         * public void line2(line_parameters, int, int)
         * {
         * }
         */

        //-------------------------------------------------------------------------
        public void line3_no_clip(line_parameters lp,
                                  int sx, int sy, int ex, int ey)
        {
            if (lp.len > LineAABasics.line_max_length)
            {
                line_parameters lp1, lp2;
                lp.divide(lp1, lp2);
                int mx = lp1.x2 + (lp1.y2 - lp1.y1);
                int my = lp1.y2 - (lp1.x2 - lp1.x1);
                line3_no_clip(lp1, (lp.x1 + sx) >> 1, (lp.y1 + sy) >> 1, mx, my);
                line3_no_clip(lp2, mx, my, (lp.x2 + ex) >> 1, (lp.y2 + ey) >> 1);
                return;
            }

            LineAABasics.fix_degenerate_bisectrix_start(lp, ref sx, ref sy);
            LineAABasics.fix_degenerate_bisectrix_end(lp, ref ex, ref ey);
            line_interpolator_image li = new line_interpolator_image(*this, lp,
                                                                     sx, sy,
                                                                     ex, ey,
                                                                     m_start, m_scale_x);

            if (li.vertical())
            {
                while (li.step_ver())
                {
                    ;
                }
            }
            else
            {
                while (li.step_hor())
                {
                    ;
                }
            }
            m_start += uround(lp.len / m_scale_x);
        }
        //---------------------------------------------------------------------
        public line_interpolator_image(renderer_outline_aa ren, line_parameters lp,
                                       int sx, int sy, int ex, int ey,
                                       int pattern_start,
                                       double scale_x)
        {
            throw new NotImplementedException();

/*
 *          m_lp=(lp);
 *          m_li = new dda2_line_interpolator(lp.vertical ? LineAABasics.line_dbl_hr(lp.x2 - lp.x1) :
 *                             LineAABasics.line_dbl_hr(lp.y2 - lp.y1),
 *               lp.vertical ? Math.Abs(lp.y2 - lp.y1) :
 *                             Math.Abs(lp.x2 - lp.x1) + 1);
 *          m_di = new distance_interpolator4(lp.x1, lp.y1, lp.x2, lp.y2, sx, sy, ex, ey, lp.len, scale_x,
 *               lp.x1 & ~LineAABasics.line_subpixel_mask, lp.y1 & ~LineAABasics.line_subpixel_mask);
 *          m_ren=ren;
 *          m_x = (lp.x1 >> LineAABasics.line_subpixel_shift);
 *          m_y = (lp.y1 >> LineAABasics.line_subpixel_shift);
 *          m_old_x=(m_x);
 *          m_old_y=(m_y);
 *          m_count = ((lp.vertical ? Math.Abs((lp.y2 >> LineAABasics.line_subpixel_shift) - m_y) :
 *                                 Math.Abs((lp.x2 >> LineAABasics.line_subpixel_shift) - m_x)));
 *          m_width=(ren.subpixel_width());
 *          //m_max_extent(m_width >> (LineAABasics.line_subpixel_shift - 2));
 *          m_max_extent = ((m_width + LineAABasics.line_subpixel_scale) >> LineAABasics.line_subpixel_shift);
 *          m_start=(pattern_start + (m_max_extent + 2) * ren.pattern_width());
 *          m_step=(0);
 *
 *          dda2_line_interpolator li = new dda2_line_interpolator(0, lp.vertical ?
 *                                            (lp.dy << LineAABasics.line_subpixel_shift) :
 *                                            (lp.dx << LineAABasics.line_subpixel_shift),
 *                                         lp.len);
 *
 *          uint i;
 *          int stop = m_width + LineAABasics.line_subpixel_scale * 2;
 *          for(i = 0; i < max_half_width; ++i)
 *          {
 *              m_dist_pos[i] = li.y();
 *              if(m_dist_pos[i] >= stop) break;
 ++li;
 *          }
 *          m_dist_pos[i] = 0x7FFF0000;
 *
 *          int dist1_start;
 *          int dist2_start;
 *          int npix = 1;
 *
 *          if(lp.vertical)
 *          {
 *              do
 *              {
 *                  --m_li;
 *                  m_y -= lp.inc;
 *                  m_x = (m_lp.x1 + m_li.y()) >> LineAABasics.line_subpixel_shift;
 *
 *                  if(lp.inc > 0) m_di.dec_y(m_x - m_old_x);
 *                  else           m_di.inc_y(m_x - m_old_x);
 *
 *                  m_old_x = m_x;
 *
 *                  dist1_start = dist2_start = m_di.dist_start();
 *
 *                  int dx = 0;
 *                  if(dist1_start < 0) ++npix;
 *                  do
 *                  {
 *                      dist1_start += m_di.dy_start();
 *                      dist2_start -= m_di.dy_start();
 *                      if(dist1_start < 0) ++npix;
 *                      if(dist2_start < 0) ++npix;
 ++dx;
 *                  }
 *                  while(m_dist_pos[dx] <= m_width);
 *                  if(npix == 0) break;
 *
 *                  npix = 0;
 *              }
 *              while(--m_step >= -m_max_extent);
 *          }
 *          else
 *          {
 *              do
 *              {
 *                  --m_li;
 *
 *                  m_x -= lp.inc;
 *                  m_y = (m_lp.y1 + m_li.y()) >> LineAABasics.line_subpixel_shift;
 *
 *                  if(lp.inc > 0) m_di.dec_x(m_y - m_old_y);
 *                  else           m_di.inc_x(m_y - m_old_y);
 *
 *                  m_old_y = m_y;
 *
 *                  dist1_start = dist2_start = m_di.dist_start();
 *
 *                  int dy = 0;
 *                  if(dist1_start < 0) ++npix;
 *                  do
 *                  {
 *                      dist1_start -= m_di.dx_start();
 *                      dist2_start += m_di.dx_start();
 *                      if(dist1_start < 0) ++npix;
 *                      if(dist2_start < 0) ++npix;
 ++dy;
 *                  }
 *                  while(m_dist_pos[dy] <= m_width);
 *                  if(npix == 0) break;
 *
 *                  npix = 0;
 *              }
 *              while(--m_step >= -m_max_extent);
 *          }
 *          m_li.adjust_forward();
 *          m_step -= m_max_extent;
 */
        }
        //---------------------------------------------------------------------
        public line_interpolator_image(IPixelFormat ren, line_parameters lp,
                                       int sx, int sy, int ex, int ey,
                                       int pattern_start,
                                       double scale_x)
        {
            m_lp = (lp);
            m_li = new dda2_line_interpolator(lp.vertical ? line_dbl_hr(lp.x2 - lp.x1) :
                                              line_dbl_hr(lp.y2 - lp.y1),
                                              lp.vertical ? abs(lp.y2 - lp.y1) :
                                              abs(lp.x2 - lp.x1) + 1);
            m_di = new distance_interpolator4(lp.x1, lp.y1, lp.x2, lp.y2, sx, sy, ex, ey, lp.len, scale_x,
                                              lp.x1 & ~line_subpixel_mask, lp.y1 & ~line_subpixel_mask);
            m_ren   = (ren);
            m_x     = (lp.x1 >> line_subpixel_shift);
            m_y     = (lp.y1 >> line_subpixel_shift);
            m_old_x = (m_x);
            m_old_y = (m_y);
            m_count = ((lp.vertical ? abs((lp.y2 >> line_subpixel_shift) - m_y) :
                        abs((lp.x2 >> line_subpixel_shift) - m_x)));
            m_width = (ren.subpixel_width());
            //m_max_extent(m_width >> (line_subpixel_shift - 2));
            m_max_extent = ((m_width + LineAABasics.line_subpixel_scale) >> line_subpixel_shift);
            m_start      = (pattern_start + (m_max_extent + 2) * ren.pattern_width());
            m_step       = (0);

            dda2_line_interpolator li = new dda2_line_interpolator(0, lp.vertical ?
                                                                   (lp.dy << LineAABasics.line_subpixel_shift) :
                                                                   (lp.dx << LineAABasics.line_subpixel_shift),
                                                                   lp.len);

            uint i;
            int  stop = m_width + LineAABasics.line_subpixel_scale * 2;

            for (i = 0; i < max_half_width; ++i)
            {
                m_dist_pos[i] = li.y();
                if (m_dist_pos[i] >= stop)
                {
                    break;
                }
                ++li;
            }
            m_dist_pos[i] = 0x7FFF0000;

            int dist1_start;
            int dist2_start;
            int npix = 1;

            if (lp.vertical)
            {
                do
                {
                    --m_li;
                    m_y -= lp.inc;
                    m_x  = (m_lp.x1 + m_li.y()) >> line_subpixel_shift;

                    if (lp.inc > 0)
                    {
                        m_di.dec_y(m_x - m_old_x);
                    }
                    else
                    {
                        m_di.inc_y(m_x - m_old_x);
                    }

                    m_old_x = m_x;

                    dist1_start = dist2_start = m_di.dist_start();

                    int dx = 0;
                    if (dist1_start < 0)
                    {
                        ++npix;
                    }
                    do
                    {
                        dist1_start += m_di.dy_start();
                        dist2_start -= m_di.dy_start();
                        if (dist1_start < 0)
                        {
                            ++npix;
                        }
                        if (dist2_start < 0)
                        {
                            ++npix;
                        }
                        ++dx;
                    }while(m_dist_pos[dx] <= m_width);
                    if (npix == 0)
                    {
                        break;
                    }

                    npix = 0;
                }while(--m_step >= -m_max_extent);
            }
            else
            {
                do
                {
                    --m_li;

                    m_x -= lp.inc;
                    m_y  = (m_lp.y1 + m_li.y()) >> line_subpixel_shift;

                    if (lp.inc > 0)
                    {
                        m_di.dec_x(m_y - m_old_y);
                    }
                    else
                    {
                        m_di.inc_x(m_y - m_old_y);
                    }

                    m_old_y = m_y;

                    dist1_start = dist2_start = m_di.dist_start();

                    int dy = 0;
                    if (dist1_start < 0)
                    {
                        ++npix;
                    }
                    do
                    {
                        dist1_start -= m_di.dx_start();
                        dist2_start += m_di.dx_start();
                        if (dist1_start < 0)
                        {
                            ++npix;
                        }
                        if (dist2_start < 0)
                        {
                            ++npix;
                        }
                        ++dy;
                    }while(m_dist_pos[dy] <= m_width);
                    if (npix == 0)
                    {
                        break;
                    }

                    npix = 0;
                }while(--m_step >= -m_max_extent);
            }
            m_li.adjust_forward();
            m_step -= m_max_extent;
        }
        //-------------------------------------------------------------------------
        public void line3(line_parameters lp,
				   int sx, int sy, int ex, int ey)
        {
            if(m_clipping)
            {
                int x1 = lp.x1;
                int y1 = lp.y1;
                int x2 = lp.x2;
                int y2 = lp.y2;
                uint flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box);
                int start = m_start;
                if((flags & 4) == 0)
                {
                    if(flags)
                    {
                        line_parameters lp2(x1, y1, x2, y2,
                                           uround(calc_distance(x1, y1, x2, y2)));
                        if(flags & 1)
                        {
                            m_start += uround(calc_distance(lp.x1, lp.y1, x1, y1) / m_scale_x);
                            sx = x1 + (y2 - y1);
                            sy = y1 - (x2 - x1);
                        }
                        else
                        {
                            while(abs(sx - lp.x1) + abs(sy - lp.y1) > lp2.len)
                            {
                                sx = (lp.x1 + sx) >> 1;
                                sy = (lp.y1 + sy) >> 1;
                            }
                        }
                        if(flags & 2)
                        {
                            ex = x2 + (y2 - y1);
                            ey = y2 - (x2 - x1);
                        }
                        else
                        {
                            while(abs(ex - lp.x2) + abs(ey - lp.y2) > lp2.len)
                            {
                                ex = (lp.x2 + ex) >> 1;
                                ey = (lp.y2 + ey) >> 1;
                            }
                        }
                        line3_no_clip(lp2, sx, sy, ex, ey);
                    }
                    else
                    {
                        line3_no_clip(lp, sx, sy, ex, ey);
                    }
                }
                m_start = start + uround(lp.len / m_scale_x);
            }
            else
            {
                line3_no_clip(lp, sx, sy, ex, ey);
            }
        }
        //---------------------------------------------------------------------
        public line_interpolator_image(IPixelFormat ren, line_parameters lp,
								int sx, int sy, int ex, int ey,
								int pattern_start,
								double scale_x)
        {
            m_lp=(lp);
            m_li = new dda2_line_interpolator(lp.vertical ? line_dbl_hr(lp.x2 - lp.x1) :
                               line_dbl_hr(lp.y2 - lp.y1),
                 lp.vertical ? abs(lp.y2 - lp.y1) :
                               abs(lp.x2 - lp.x1) + 1);
            m_di = new distance_interpolator4(lp.x1, lp.y1, lp.x2, lp.y2, sx, sy, ex, ey, lp.len, scale_x,
                 lp.x1 & ~line_subpixel_mask, lp.y1 & ~line_subpixel_mask);
            m_ren=(ren);
            m_x=(lp.x1 >> line_subpixel_shift);
            m_y=(lp.y1 >> line_subpixel_shift);
            m_old_x=(m_x);
            m_old_y=(m_y);
            m_count=((lp.vertical ? abs((lp.y2 >> line_subpixel_shift) - m_y) :
                                   abs((lp.x2 >> line_subpixel_shift) - m_x)));
            m_width=(ren.subpixel_width());

            //m_max_extent(m_width >> (line_subpixel_shift - 2));
            m_max_extent=((m_width + LineAABasics.line_subpixel_scale) >> line_subpixel_shift);
            m_start=(pattern_start + (m_max_extent + 2) * ren.pattern_width());
            m_step=(0);

            dda2_line_interpolator li = new dda2_line_interpolator(0, lp.vertical ?
                                              (lp.dy << LineAABasics.line_subpixel_shift) :
                                              (lp.dx << LineAABasics.line_subpixel_shift),
                                           lp.len);

            uint i;
            int stop = m_width + LineAABasics.line_subpixel_scale * 2;
            for(i = 0; i < max_half_width; ++i)
            {
                m_dist_pos[i] = li.y();
                if(m_dist_pos[i] >= stop) break;
                ++li;
            }
            m_dist_pos[i] = 0x7FFF0000;

            int dist1_start;
            int dist2_start;
            int npix = 1;

            if(lp.vertical)
            {
                do
                {
                    --m_li;
                    m_y -= lp.inc;
                    m_x = (m_lp.x1 + m_li.y()) >> line_subpixel_shift;

                    if(lp.inc > 0) m_di.dec_y(m_x - m_old_x);
                    else           m_di.inc_y(m_x - m_old_x);

                    m_old_x = m_x;

                    dist1_start = dist2_start = m_di.dist_start();

                    int dx = 0;
                    if(dist1_start < 0) ++npix;
                    do
                    {
                        dist1_start += m_di.dy_start();
                        dist2_start -= m_di.dy_start();
                        if(dist1_start < 0) ++npix;
                        if(dist2_start < 0) ++npix;
                        ++dx;
                    }
                    while(m_dist_pos[dx] <= m_width);
                    if(npix == 0) break;

                    npix = 0;
                }
                while(--m_step >= -m_max_extent);
            }
            else
            {
                do
                {
                    --m_li;

                    m_x -= lp.inc;
                    m_y = (m_lp.y1 + m_li.y()) >> line_subpixel_shift;

                    if(lp.inc > 0) m_di.dec_x(m_y - m_old_y);
                    else           m_di.inc_x(m_y - m_old_y);

                    m_old_y = m_y;

                    dist1_start = dist2_start = m_di.dist_start();

                    int dy = 0;
                    if(dist1_start < 0) ++npix;
                    do
                    {
                        dist1_start -= m_di.dx_start();
                        dist2_start += m_di.dx_start();
                        if(dist1_start < 0) ++npix;
                        if(dist2_start < 0) ++npix;
                        ++dy;
                    }
                    while(m_dist_pos[dy] <= m_width);
                    if(npix == 0) break;

                    npix = 0;
                }
                while(--m_step >= -m_max_extent);
            }
            m_li.adjust_forward();
            m_step -= m_max_extent;
        }
        /*

        //-------------------------------------------------------------------------
        public void semidot(Cmp, int, int, int, int)
        {
        }

        //-------------------------------------------------------------------------
        public void pie(int, int, int, int, int, int)
        {
        }

        //-------------------------------------------------------------------------
        public void line0(line_parameters)
        {
        }

        //-------------------------------------------------------------------------
        public void line1(line_parameters, int, int)
        {
        }

        //-------------------------------------------------------------------------
        public void line2(line_parameters, int, int)
        {
        }
         */
        //-------------------------------------------------------------------------
        public void line3_no_clip(line_parameters lp,
						   int sx, int sy, int ex, int ey)
        {
            if(lp.len > LineAABasics.line_max_length)
            {
                line_parameters lp1, lp2;
                lp.divide(lp1, lp2);
                int mx = lp1.x2 + (lp1.y2 - lp1.y1);
                int my = lp1.y2 - (lp1.x2 - lp1.x1);
                line3_no_clip(lp1, (lp.x1 + sx) >> 1, (lp.y1 + sy) >> 1, mx, my);
                line3_no_clip(lp2, mx, my, (lp.x2 + ex) >> 1, (lp.y2 + ey) >> 1);
                return;
            }

            LineAABasics.fix_degenerate_bisectrix_start(lp, ref sx, ref sy);
            LineAABasics.fix_degenerate_bisectrix_end(lp, ref ex, ref ey);
            line_interpolator_image li = new line_interpolator_image(*this, lp,
                                                  sx, sy,
                                                  ex, ey,
                                                  m_start, m_scale_x);
            if(li.vertical())
            {
                while(li.step_ver());
            }
            else
            {
                while(li.step_hor());
            }
            m_start += uround(lp.len / m_scale_x);
        }