/** 
 *  Yudit Unicode Editor Source File
 *
 *  GNU Copyright (C) 1997-2023  Gaspar Sinai <gaspar@yudit.org>  
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License, version 2,
 *  dated June 1991. See file COPYYING for details.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include "swindow/SAwt.h"
#include "swidget/SBorder.h"

static void borderBitPoint (SCanvas* canvas, const SColor& fg, int x, int y, int width) {
    if (width == 1) {
        canvas->bitpoint (fg, x, y);
        return;
   }
   canvas->bitfill (fg, x, y, width, width);
}


static void borderBitline (SCanvas* canvas, const SColor& fg, int x, int y, int tox, int toy, int width) {
   if (width == 1) {
        canvas->bitline (fg, x, y, tox, toy);
        return;
   }
    if (x == tox) {
        int size = toy > y ? toy - y : y - toy;
        int offset = toy > y ? 0 : y - toy;
        canvas->bitfill (fg, x, y-offset, width, size+width);
        return;
    }
    if (y == toy) {
        int size = tox > x ? tox - x : x - tox;
        int offset = tox > x ? 0 : x - tox;
        canvas->bitfill (fg, x-offset, y, size+width, width);
        return;
    }
}

/**
 * Craet a border object.
 * the borderSize is the x and y dimension of the border.
 * The actual component size reduces by this twice for x and y directions too
 */
SBorder::SBorder (SStyle s)
{
  style = s;
  borderScale = SAwt::getRasterScale();
  borderSize = SDimension (borderScale*2,borderScale*2);
}

SBorder::~SBorder ()
{
}

void
SBorder::setStyle (SStyle s)
{
  style = s;
}

const SDimension&
SBorder::getBorderSize() const
{
  return borderSize;
}

// can be manually activated using: setNeedDisplay: YES
void
SBorder::redraw (SCanvas *canvas, int _x, int _y, unsigned int width, unsigned int height)
{
  SColor di = background.darker();
  SColor li = background.lighter();
  SColor vi = background.isDark() ? li : di;
  for (int i=0; i<borderScale; i++) {
    int BS = borderScale;
    /* locations with ending points */
    int x[2] = { location.x, location.x + (int) size.width-BS };
    int y[2] = { location.y, location.y + (int) size.height-BS };
    switch (style)
    {
    case ETCHED:
      //  +----
      //  |
      //
      borderBitline (canvas, di, x[0], y[0], x[1]-BS, y[0], BS);
      borderBitline (canvas, di, x[0], y[0]+BS, x[0], y[1]-BS, BS);
      //    +----
      //    |
      borderBitline (canvas, li, x[0]+BS, y[0]+BS, x[1]-2*BS, y[0]+BS, BS);
      borderBitline (canvas, li, x[0]+BS, y[0]+2*BS, x[0]+BS, y[1]-2*BS, BS);
      //        |
      //     ---+
      borderBitline (canvas, di, x[1]-BS, y[0]+2*BS, x[1]-BS, y[1]-BS, BS);
      borderBitline (canvas, di, x[1]-BS, y[1]-BS, x[0]+2*BS, y[1]-BS, BS);
      //         |
      //      ---+
      borderBitline (canvas, li, x[1], y[0]+BS, x[1], y[1], BS);
      borderBitline (canvas, li, x[1], y[1], x[0]+BS, y[1], BS);
      //         +
      //     +
      borderBitPoint (canvas, background, x[1]-BS, y[0]+BS, BS);
      borderBitPoint (canvas, background, x[0]+BS, y[1]-BS, BS);
      borderBitPoint (canvas, background, x[0], y[1], BS);
      borderBitPoint (canvas, background, x[1], y[0], BS);
      break;
    case IN:
      borderBitline (canvas, di, x[0], y[0], x[1], y[0], BS); 
      // lower left corrner is light
      borderBitline (canvas, di, x[0], y[0]+BS, x[0], y[1]-BS, BS);
      borderBitline (canvas, li, x[1], y[0], x[1], y[1], BS);
      borderBitline (canvas, li, x[0], y[1], x[1], y[1], BS);
      break;
    case OUT:
      break;
    case SOLID:
      borderBitline (canvas, background, x[0], y[0], x[1]-BS, y[0], BS); 
      borderBitline (canvas, background, x[1], y[0], x[1], y[1]-BS, BS);
      borderBitline (canvas, background, x[0]+BS, y[1],  x[1], y[1], BS);
      borderBitline (canvas, background, x[0], y[0]+1, x[0], y[1], BS);
      break;
    case SOLID_VISIBLE:
      borderBitline (canvas, vi, x[0], y[0], x[1]-BS, y[0], BS); 
      borderBitline (canvas, vi, x[1], y[0], x[1], y[1]-BS, BS);
      borderBitline (canvas, vi, x[0]+BS, y[1],  x[1], y[1], BS);
      borderBitline (canvas, vi, x[0], y[0]+1, x[0], y[1], BS);
      break;
    }
  }
  return;
}

void
SBorder::resize (const SDimension& s)
{
  SComponent::resize(s);
}

void 
SBorder::move (const SLocation& l)
{
  SComponent::move(l);
}
void
SBorder::changeStyle (SStyle newStyle) 
{
    style = newStyle;
}
