/*
 * MandelVroom 2.0
 *
 * (c) Copyright 1987,1989  Kevin L. Clague, San Jose, CA
 *
 * All rights reserved.
 *
 * Permission is hereby granted to distribute this program's source
 * executable, and documentation for non-comercial purposes, so long as the
 * copyright notices are not removed from the sources, executable or
 * documentation.  This program may not be distributed for a profit without
 * the express written consent of the author Kevin L. Clague.
 *
 * This program is not in the public domain.
 *
 * Fred Fish is expressly granted permission to distribute this program's
 * source and executable as part of the "Fred Fish freely redistributable
 * Amiga software library."
 *
 * Permission is expressly granted for this program and it's source to be
 * distributed as part of the Amicus Amiga software disks, and the
 * First Amiga User Group's Hot Mix disks.
 *
 * contents: this file contains the functions to open, draw and close the
 * histogram window.
 */

#include "mandp.h"

UBYTE HistOpen;

struct Window          *HistWind;

struct NewWindow NewHist = {
   0,200-80,                 /* start position           */
   280,80,                   /* width, height            */
   (UBYTE) 0, (UBYTE) -1,    /* detail pen, block pen    */
   NULL,                     /* IDCMP flags */
                             /* MandWind flags */
   WINDOWCLOSE|WINDOWDRAG|WINDOWDEPTH|NOCAREREFRESH|SMART_REFRESH,
   (struct Gadget *) NULL,   /* first gadget             */
   (struct Image *) NULL,    /* user checkmark           */
   (UBYTE *) "Histogram",     /* window title             */
   (struct Screen *) NULL,   /* pointer to screen        */
   (struct BitMap *) NULL,   /* pointer to superbitmap   */
   80,80,-1,-1,              /* sizing                   */
   CUSTOMSCREEN              /* type of screen           */
   };

struct Histogram *
AllocHist( size )
  int size;
{
  struct Histogram *Hist;

  Hist = AllocHistStruct();

  if (Hist != NULL) {

    if (Hist->Table == NULL) {

      Hist->Table = AllocHistTable(size);

      if (Hist->Table == NULL) {

        FreeHistStruct(Hist);
        return( NULL );
      }

      Hist->TableSize = size;
    }
  }
  return( Hist );
}

FreeHist( Hist )
  struct Histogram *Hist;
{
  if (Hist) {

    if (Hist->Table) {
      FreeHistTable( Hist );
    }
    FreeHistStruct( Hist );
  }
}

ReDoHist( Pict )
  register struct Picture *Pict;
{
  if (Pict == NULL || Pict->Counts == NULL ||
      Pict->Flags & NO_RAM_GENERATE || HistWind == NULL) {

    return(UNSUCCESSFUL );
  }
  CalcHist(Pict);
  PlotHist(Pict);
}

/*
 *
 */
CalcHist(Pict)
  register struct Picture *Pict;
{
  register int i, n, size, *Table;
  register SHORT *Counts;

  /* make sure the histogram is available */

  if (Pict->Hist) {
    FreeHist( Pict->Hist );
    Pict->Hist = NULL;
  }

  if (Pict == NULL || Pict->Flags & NO_RAM_GENERATE ||
      Pict->Counts == NULL) {

    return;
  }

  Pict->Hist = AllocHist( Pict->MaxIteration );

  if (Pict->Hist == NULL) {
    return;
  }

  Table = Pict->Hist->Table;
  size  = Pict->Hist->TableSize;

  for (i = 0; i < size; i++) {
    Table[i] = 0;
  }

  Counts = Pict->Counts;
  size   = Pict->CountX*Pict->CountY;

  for (i = 0; i < size; i++) {

    if ( (n = *Counts++) > 0 && n < Pict->Hist->TableSize) {

      Table[ n ]++;
    }
  }
}

PlotHist( Pict )
  struct Picture *Pict;
{
  register struct Histogram *Hist;
  int *Table; int  Size;
  int  max, locmax, maxnum;

  struct IntuiText *intui;

  BorderWindow( HistWind );

  Hist = Pict->Hist;

  if (Hist == NULL) {
    return;
  }

  Table = (int *) Hist->Table;
  Size  = Hist->TableSize;

  /* Find Max of all iteration counts */

  { int i,n;

    max = 0;

    for (i = 0; i < Size; i++) {
      if ((n = *Table++) > max) {
        max = n;
      }
    }
  }

#define BOX_BOT  24
#define BOX_LEFT 17
#define BOX_TOP  22

  Table = (int *) Hist->Table;

  /* Plot scaled versions of this histogram */

  { int bot,right,half;
    int i, j, k, n, height,width;
    int num_entries;
    float scale;
    register struct RastPort *Rp = HistWind->RPort;

    if (XScale) {
      k = 2;
    } else {
      k = 4;
    }

    num_entries = 1024/k;
    right = BOX_LEFT + num_entries;
    half = num_entries/2 + BOX_LEFT;
    bot  = HistWind->Height - BOX_BOT;
    scale = (float)(bot-BOX_TOP)/(float)max;

    Rp = HistWind->RPort;

    SetAPen(  Rp, NORMALPEN );
    RectFill( Rp, LEFTMARG, TOPMARG, HistWind->Width-2, HistWind->Height-2);

    /* Draw plot border */

    SetAPen(Rp,SHADOWPEN);
    Move(Rp,right+1,  bot+1);     /* Lower right */
    Draw(Rp,right+1,  BOX_TOP);   /* Upper right */
    Draw(Rp,BOX_LEFT,BOX_TOP);   /* Upper left  */
    Draw(Rp,BOX_LEFT,bot+1);     /* Lower left  */
    Draw(Rp,right+1,  bot+1);     /* Lower right */

    Move(Rp,BOX_LEFT,bot+2);     /* Lower left tic */
    Draw(Rp,BOX_LEFT,bot+3);

    /* Do altitude tick marks */

    for (i = 0; i < num_entries; i += 16<<XScale) {
      Move(Rp, right - i + 1, bot+2);
      Draw(Rp, right - i + 1, bot+3);
    }

    intui = ShadowIntui("1023", BOX_LEFT-16, bot + 5);
    PrintIText( Rp, intui, 0, 0);
    FreeIntui(intui);

    intui = ShadowIntui("512", half-12, bot + 5);
    PrintIText( Rp, intui, 0, 0);
    FreeIntui(intui);

    intui = ShadowIntui("0", right-4, bot + 5);
    PrintIText( Rp, intui, 0, 0);
    FreeIntui(intui);

    intui = ShadowIntui("Height", half-24, bot + 13);
    PrintIText( Rp, intui, 0, 0);
    FreeIntui(intui);

    intui = ShadowIntui("Percentage (10%/Tick)", half-84, BOX_TOP-11);
    PrintIText( Rp, intui, 0, 0);
    FreeIntui(intui);

    /* Do percentage tick marks */

    SetAPen(Rp,HIGHLIGHTPEN);
    Move(Rp,right+1,  BOX_TOP-1); /* right */
    Draw(Rp,right+1,  BOX_TOP-2);
    Move(Rp,BOX_LEFT,BOX_TOP-1); /* left  */
    Draw(Rp,BOX_LEFT,BOX_TOP-2);

    { int tick = Pict->CountX*Pict->CountY/10;
      int thresh, cur;

      cur = 0;
      thresh = tick;

      for (i = Size-1; i >= 0; i--) {
        cur += Table[i];
        if (cur > thresh) {
          Move(Rp, right - (i/(4>>XScale)) + 1, BOX_TOP-1);
          Draw(Rp, right - (i/(4>>XScale)) + 1, BOX_TOP-2);
          thresh += tick;
        }
      }
    }

    for (i = 0; i < Size; i += k) {

      n = Table[i];
      locmax = n;
      maxnum = i;

      for (j = 0; j < 4; j++) {

        n = Table[i+j];

        if (n > locmax) {
          locmax = n;
          maxnum = i+j;
        }
      }

      if ( locmax > 0 ) {

        height = bot - (int) (scale * locmax);

        if (right   < HistWind->Width && height >= 0 &&
            height < HistWind->Height) {

          SetAPen( Rp, Pict->ClrXlate[maxnum] );

          Move(Rp, right, bot);
          Draw(Rp, right, height);
        }
      }
      right -= 1;
    }
  }
}

AutoContour( Pict, Mode )
  struct Picture *Pict;
{
  int num_conts,i,j,prev_i;

  float tick;
  float thresh, cur;

  if (Pict == NULL || Pict->Flags & NO_RAM_GENERATE ||
      Pict->Counts == NULL) {
    return;
  }

  CalcHist(Pict);

  if (Pict->Hist == NULL)
    return;

  /* find pattern range length */

  for (num_conts = 255; num_conts >= 0 && Pict->Pens[num_conts] == 1;
       num_conts--);

  if (num_conts == 0)
    return;

  /* Set up contours */

  j = 0;

  for (i = 0 ; i < Pict->Hist->TableSize - 1; i++) {
     j += Pict->Hist->Table[i];
  }

  thresh = tick = (float) (j) / (float) num_conts;
  cur = 0.0;

  Pict->Heights[0] = Pict->MaxIteration;
  j = 1;
  prev_i = 0;

  for (i = Pict->Hist->TableSize - 2; i >= 0 && j < num_conts-1; i--) {

    cur += Pict->Hist->Table[i];

    if (cur > thresh) {

      Pict->Heights[j++] = i;

      if (Mode == 1 && i+1 == prev_i) {
        break;   /* out of the loop */
      }
      prev_i = i;

      while ( cur > thresh )
        thresh += tick;
    }
  }
  if (i < 0)
    i = 0;

  for (; j < num_conts-1; j++) {

    if (i > 0) i--;

    Pict->Heights[j] = i;
  }
  Pict->Heights[j] = 0;
  if (ContWind) {
    ModAll();
  }
  ReColor( Pict );
}

/*
 * Open the Hist window
 */
OpenHistWind()
{

  if (CurPict == NULL)
    return;

  if ( HistWind == NULL ) {

    HistWind = OpenMyWind( &NewHist, screen, NULL,280<<XScale,96+32*YScale);

    if ( HistWind == NULL ) {
      return;
    }
  } else {
    WindowToFront( HistWind );
  }
  ReDoHist(CurPict);
  HistOpen = 1;
} /* OpenHistWind */

/*
 * Close the Hist window
 */
CloseHistWind()
{
  if (HistWind != NULL) {

    NewHist.LeftEdge = HistWind->LeftEdge;
    NewHist.TopEdge  = HistWind->TopEdge;

    CloseMyWind(HistWind,NULL);
  }
  HistWind = NULL;
} /* CloseHistWind */

