
class ploter
{
public:
    ploter() {}
    virtual void operator() (int x, int y, Uint8 color) { }
};

class getter
{
public:
    getter() {}
    virtual Uint8 operator() (int x, int y) { }
};


class bresenhamCircle
{
    ploter * setPixel;
public:
    bresenhamCircle(ploter &plotFunctor)
    {
        setPixel = &plotFunctor;
    }
    void operator () (int xc, int yc, Uint8 color, int r)
    {
        int x = 0;
        int y = r;
        int p = 3 - 2 * r;
        if (!r) return;
        while (y >= x) // only formulate 1/8 of circle
        {
            (*setPixel)(xc-x, yc-y, color);//upper left left
            (*setPixel)(xc-y, yc-x, color);//upper upper left
            (*setPixel)(xc+y, yc-x, color);//upper upper right
            (*setPixel)(xc+x, yc-y, color);//upper right right
            (*setPixel)(xc-x, yc+y, color);//lower left left
            (*setPixel)(xc-y, yc+x, color);//lower lower left
            (*setPixel)(xc+y, yc+x, color);//lower lower right
            (*setPixel)(xc+x, yc+y, color);//lower right right
            if (p < 0) p += 4*x++ + 6;
                  else p += 4*(x++ - y--) + 10;
         }
    }
};

class bresenhamLine
{
    ploter * setPixel;
public:
    bresenhamLine(ploter &plotFunctor)
    {
        setPixel = &plotFunctor;
    }
    void operator () (int x1, int y1, int x2, int y2, Uint8 color)
    {
        // if x1 == x2 or y1 == y2, then it does not matter what we set here
        int delta_x = (x2 - x1);
        signed char ix = ((delta_x > 0) - (delta_x < 0));
        if (delta_x < 0) delta_x=-delta_x;
        delta_x = delta_x << 1;

        int delta_y(y2 - y1);
        signed char iy((delta_y > 0) - (delta_y < 0));
        if (delta_y < 0) delta_y=-delta_y;
        delta_y = delta_y << 1;

        (*setPixel)(x1, y1,color);

        if (delta_x >= delta_y)
        {
            // error may go below zero
            int error = (delta_y - (delta_x >> 1));

            while (x1 != x2)
            {
                if (error >= 0)
                {
                    if (error || (ix > 0))
                    {
                        y1 += iy;
                        error -= delta_x;
                    }
                    // else do nothing
                }
                // else do nothing

                x1 += ix;
                error += delta_y;

                (*setPixel)(x1, y1,color);
            }
        }
        else
        {
            // error may go below zero
            int error = (delta_x - (delta_y >> 1));

            while (y1 != y2)
            {
                if (error >= 0)
                {
                    if (error || (iy > 0))
                    {
                        x1 += ix;
                        error -= delta_y;
                    }
                    // else do nothing
                }
                // else do nothing

                y1 += iy;
                error += delta_x;

                (*setPixel)(x1, y1,color);
            }
        }
//        int dx=x1-x0;
//        int dy=y1-y0;

//        int D = 2*dy - dx;
//        (*setPixel)(x0,y0,color);
//        int y=y0;

//        for (int x = x0+1; x < x1; x++)
//        {
//            if (D > 0)
//            {
//                y = y+1;
//                (*setPixel)(x,y,color);
//                D = D + (2*dy-2*dx);
//            }
//            else
//            {
//                (*setPixel)(x,y,color);
//                D = D + (2*dy);
//            }
//        }
    }
};

class floodFill
{
    ploter * setPixel;
    getter * getPixel;
public:
/*
Flood-fill (node, target-color, replacement-color):
 1. If the color of node is not equal to target-color, return.
 2. Set the color of node to replacement-color.
 3. Perform Flood-fill (one step to the west of node, target-color, replacement-color).
    Perform Flood-fill (one step to the east of node, target-color, replacement-color).
    Perform Flood-fill (one step to the north of node, target-color, replacement-color).
    Perform Flood-fill (one step to the south of node, target-color, replacement-color).
 4. Return
*/
    floodFill(ploter & plot, getter & get)
    {
        setPixel = & plot;
        getPixel = & get;
    }
    void operator () (int x, int y, Uint8 color, Uint8 background)
    {
        if ( (*getPixel)(x,y) != background)
            return;
        (*setPixel)(x,y,color);
        operator () (x,y-1,color,background);
        operator () (x+1,y,color,background);
        operator () (x,y+1,color,background);
        operator () (x-1,y,color,background);
    }
};
