/*****************************************************************************
 *
 * Nom:                         tracewin.c
 * Desc:                        fonctions de traçage dans les fenetres
 *
 *
 * version                      : $VER: tracewin.c 2.4 (10.01.99)
 *
 * ver2.3: fill background or transparent
 * ver2.3ß3: CyberGraphics support (beta)
 * ver2.3ß4: BugFixed but beta CGX
 * ver2.3ß5: Filled needles(option), no direct CGX support (deleted)
 * ver2.4  : added shadow and middle point drawings
 *****************************************************************************
 */ 
#include <exec/memory.h>
#include <graphics/rastport.h>
#include <proto/graphics.h>
#include <proto/exec.h>
#include <math.h>
#include "utils.h"
#include "tracewin.h"
#include <graphics/gfxmacros.h>


/*UWORD area_pat[] = {
  0xf0f0,0xf0f0,0xf0f0, 0xf0f0, 0x0f0f, 0x0f0f, 0x0f0f, 0x0f0f
} ;*/

PLANEPTR tmpbitmap ;
USHORT Xplane, Yplane ;

struct pt ptSec,
          ptMin,
          ptHeu ;
ULONG mX, mY ;

void initwin(idWin * prj) {
  int i ;
  
  mX = prj->backWin.width / 2 ;
  mY = prj->backWin.height / 2 ;
  if (prj->RP1) {
    if(prj->backWin.fill) {
      SetAPen(prj->RP1, prj->backWin.cmap[COL_BAC].reg) ;
      RectFill(prj->RP1, 0, 0, prj->backWin.width-1, prj->backWin.height-1) ;
    }
    SetAPen(prj->RP1, prj->backWin.cmap[COL_TIC].reg) ;                                                       // couleur jaune
    for(i = 0; i < 360; i+=30) {
      /* trace les repères des heures
      */
      Move(prj->RP1, ULONG(cos(PI*i/180.0) * (mX-mX/10L)) + mX, ULONG(sin(PI*i/180.0) * (mY-mY/10L)) + mY) ;
      Draw(prj->RP1, ULONG(cos(PI*i/180.0) * mX) + mX, ULONG(sin(PI*i/180.0) * mY) + mY) ;
    }
    
  }
  /* initalisation des points des aiguilles
   */
  /* secondes
   */
  ptSec.points = 2 ;
  ptSec.fill   = FALSE ;
  ptSec.pt_buffer = NULL ; // idem
  ptSec.A[0]   = 0 ;
  ptSec.A[1]   = 180 ;
  ptSec.M[0]   = 5.0 ;
  ptSec.M[1]   = 1.2 ;
  ptSec.angle  = ANGLE_S ;
  /* heures
   */
  ptHeu.points = 5 ;
  ptHeu.fill   = TRUE ;
  ptHeu.pt_buffer = AllocVec(10 * ptHeu.points, MEMF_PUBLIC) ;
  ptHeu.A[0]   = 0 ;
  ptHeu.A[1]   = 100 ;
  ptHeu.A[2]   = 180 ;
  ptHeu.A[3]   = -100 ;
  ptHeu.A[4]   = 0 ;
  ptHeu.M[0]   = 3.0 ;
  ptHeu.M[1]   = 1.1 ;
  ptHeu.M[2]   = 1.2 ;
  ptHeu.M[3]   = 1.1 ;
  ptHeu.M[4]   = 3.0 ;
  ptHeu.angle  = ANGLE_H ;
  
  /* minutes
   */
  ptMin.points =   5 ;
  ptMin.fill   = TRUE ;
  ptMin.pt_buffer = AllocVec(10 * ptMin.points, MEMF_PUBLIC) ;
  ptMin.A[0]   =   0 ;
  ptMin.A[1]   =  150 ;
  ptMin.A[2]   = 180 ;
  ptMin.A[3]   = -150 ;
  ptMin.A[4]   =   0 ;
  ptMin.M[0]   =   4 ;
  ptMin.M[1]   =   1.3 ;
  ptMin.M[2]   =   1.2 ;
  ptMin.M[3]   =   1.3 ;
  ptMin.M[4]   =   4 ;
  ptMin.angle  = ANGLE_M ;
  
  prj->ai     = AllocVec(sizeof(struct AreaInfo), MEMF_PUBLIC|MEMF_CLEAR) ;

  //SetAfPt(prj->RP2, area_pat, 3) ;
  effacer(prj) ;
  retracer(prj) ;

}
void free_twin(idWin * prj) {
  /* free vertice buffer
   * areainfo and tmpras buffer
   */
  if (ptSec.pt_buffer) FreeVec(ptSec.pt_buffer) ;
  if (ptMin.pt_buffer) FreeVec(ptMin.pt_buffer) ;
  if (ptHeu.pt_buffer) FreeVec(ptHeu.pt_buffer) ;
  if (prj->ai)         FreeVec(prj->ai) ;
}

void reinit_win(idWin * prj) {
  free_twin(prj) ;
  initwin(prj) ;
}

void effacer(idWin * prj) {
//  BltBitMapRastPort(prj->wb->RastPort.BitMap, prj->backWin.posX, prj->backWin.posY, prj->RP1, 0, 0, prj->backWin.width, prj->backWin.height, 0xc0) ;
  WaitBlit() ;
  BltBitMapRastPort(prj->RP1->BitMap, 0,0, prj->RP2, 0, 0, prj->backWin.width, prj->backWin.height, 0xc0) ;
}
void retracer(idWin * prj) {
  UWORD patt[]={0x5555,0xaaaa} ;
  if (prj->backWin.drawsha) {
    //drawShadow()
    prj->RP2->AreaPtrn = patt ;
    prj->RP2->AreaPtSz = 1 ; 
    SetDrMd(prj->RP2, JAM1) ;
    SetAPen(prj->RP2, prj->backWin.cmap[COL_BLA].reg) ;
    tracerOmbre(prj, &ptHeu, prj->heu, prj->min/2) ;
    tracerOmbre(prj, &ptMin, prj->min, NULL) ;
    if (prj->backWin.drawsec) {
      prj->RP2->LinePtrn = 0xaaaa ;
      tracerOmbre(prj, &ptSec, prj->sec, NULL) ;
      prj->RP2->LinePtrn = 0xffff ;
    }
    prj->RP2->AreaPtrn = NULL ; 
  }
  SetAPen(prj->RP2, prj->backWin.cmap[COL_HEU].reg) ;
  tracerAiguilles(prj, &ptHeu, prj->heu, prj->min/2) ;
  SetAPen(prj->RP2, prj->backWin.cmap[COL_MIN].reg) ;
  tracerAiguilles(prj, &ptMin, prj->min, NULL) ;
  if (prj->backWin.drawsec) {
    SetAPen(prj->RP2, prj->backWin.cmap[COL_SEC].reg) ;
    tracerAiguilles(prj, &ptSec, prj->sec, NULL) ;
  }
  if(prj->backWin.drawmpo) {
    SetAPen(prj->RP2, prj->backWin.cmap[COL_MPO].reg) ;
    WritePixel(prj->RP2, mX, mY) ;
    WritePixel(prj->RP2, mX-1, mY) ;
    WritePixel(prj->RP2, mX, mY-1) ;
    WritePixel(prj->RP2, mX-1, mY-1) ;
    WritePixel(prj->RP2, mX+1, mY) ;
    WritePixel(prj->RP2, mX, mY+1) ;
    WritePixel(prj->RP2, mX+1, mY+1) ;
    
    
    
  }

  WaitBlit() ;
  BltBitMapRastPort(prj->RP2->BitMap, 0,0, prj->win->RPort, 0, 0, prj->backWin.width, prj->backWin.height, 0xc0) ;
 
}
void tracerAiguilles(idWin * prj, struct pt * ptAigu, UBYTE p_time, UBYTE an_inc) {
  /*
   * Trace une aiguille
   */
  int i ;
  
  Move(prj->RP2, mX+(ULONG)(cos(PI*(ptAigu->A[0]+p_time*ptAigu->angle+an_inc-90.0)/180.0)*(mX-mX/ptAigu->M[0])), 
                        mY+(ULONG)(sin(PI*(ptAigu->A[0]+p_time*ptAigu->angle+an_inc-90.0)/180.0)*(mY-mY/ptAigu->M[0]))) ;

  if (!ptAigu->fill || (prj->backWin.filln == 0)) {
    // tracer sans remplissage
    // no fill
    for(i = 0; i<ptAigu->points; i++)
      Draw(prj->RP2, mX+(ULONG)(cos(PI*(ptAigu->A[i]+p_time*ptAigu->angle+an_inc-90.0)/180.0)*(mX-mX/ptAigu->M[i])), 
                            mY+(ULONG)(sin(PI*(ptAigu->A[i]+p_time*ptAigu->angle+an_inc-90.0)/180.0)*(mY-mY/ptAigu->M[i]))) ;
  }else {
    // avec remplissage
    // fill
    prj->RP2->AreaInfo = prj->ai ;
    InitArea(prj->ai, ptAigu->pt_buffer, ptAigu->points+2) ;
    
    AreaMove(prj->RP2, (SHORT)mX+(ULONG)(cos(PI*(ptAigu->A[0]+p_time*ptAigu->angle+an_inc-90.0)/180.0)*(mX-mX/ptAigu->M[0])), 
                              (SHORT)mY+(ULONG)(sin(PI*(ptAigu->A[0]+p_time*ptAigu->angle+an_inc-90.0)/180.0)*(mY-mY/ptAigu->M[0]))) ;

    for(i = 0; i < ptAigu->points; i++) 
      AreaDraw(prj->RP2, (SHORT)mX+(ULONG)(cos(PI*(ptAigu->A[i]+p_time*ptAigu->angle+an_inc-90.0)/180.0)*(mX-mX/ptAigu->M[i])), 
                                (SHORT)mY+(ULONG)(sin(PI*(ptAigu->A[i]+p_time*ptAigu->angle+an_inc-90.0)/180.0)*(mY-mY/ptAigu->M[i]))) ;
      
    AreaEnd(prj->RP2) ;
  }
}
void tracerOmbre(idWin * prj, struct pt * ptAigu, UBYTE p_time, UBYTE an_inc) {
  /* trace l'ombre de l'aiguille
   */
  int i ;
  LONG offset ;
  
  offset = (5 * ((mX*2 + mY*2) / 2.0))/135.0 ;
  
  Move(prj->RP2, offset+mX+(ULONG)(cos(PI*(ptAigu->A[0]+p_time*ptAigu->angle+an_inc-90.0)/180.0)*(mX-mX/ptAigu->M[0])), 
                        offset+mY+(ULONG)(sin(PI*(ptAigu->A[0]+p_time*ptAigu->angle+an_inc-90.0)/180.0)*(mY-mY/ptAigu->M[0]))) ;

  if (!ptAigu->fill || (prj->backWin.filln == 0)) {
    // tracer sans remplissage
    // no fill
    for(i = 0; i<ptAigu->points; i++)
      Draw(prj->RP2, offset+mX+(ULONG)(cos(PI*(ptAigu->A[i]+p_time*ptAigu->angle+an_inc-90.0)/180.0)*(mX-mX/ptAigu->M[i])), 
                            offset+mY+(ULONG)(sin(PI*(ptAigu->A[i]+p_time*ptAigu->angle+an_inc-90.0)/180.0)*(mY-mY/ptAigu->M[i]))) ;
  }else {
    // avec remplissage
    // fill
    prj->RP2->AreaInfo = prj->ai ;
    InitArea(prj->ai, ptAigu->pt_buffer, ptAigu->points+2) ;
    
    AreaMove(prj->RP2, offset+(SHORT)mX+(ULONG)(cos(PI*(ptAigu->A[0]+p_time*ptAigu->angle+an_inc-90.0)/180.0)*(mX-mX/ptAigu->M[0])), 
                              offset+(SHORT)mY+(ULONG)(sin(PI*(ptAigu->A[0]+p_time*ptAigu->angle+an_inc-90.0)/180.0)*(mY-mY/ptAigu->M[0]))) ;

    for(i = 0; i < ptAigu->points; i++) 
      AreaDraw(prj->RP2, offset+(SHORT)mX+(ULONG)(cos(PI*(ptAigu->A[i]+p_time*ptAigu->angle+an_inc-90.0)/180.0)*(mX-mX/ptAigu->M[i])), 
                                offset+(SHORT)mY+(ULONG)(sin(PI*(ptAigu->A[i]+p_time*ptAigu->angle+an_inc-90.0)/180.0)*(mY-mY/ptAigu->M[i]))) ;
      
    AreaEnd(prj->RP2) ;
  }
}
void init_bitmap(idWin * prj) {
  /* initialize tmp rastport and bitmap
   */
  prj->tmpras = AllocVec(sizeof(struct TmpRas), MEMF_PUBLIC|MEMF_CLEAR) ;
  prj->RP1 = AllocVec(sizeof(struct RastPort), MEMF_PUBLIC) ;
  prj->RP2 = AllocVec(sizeof(struct RastPort), MEMF_PUBLIC) ; 
  InitRastPort(prj->RP1) ;
  InitRastPort(prj->RP2) ;
  Xplane = prj->backWin.width ;
  Yplane = prj->backWin.height ; 
  prj->RP1->BitMap = AllocBitMap(Xplane, Yplane, prj->wb->RastPort.BitMap->Depth, BMF_CLEAR|BMF_DISPLAYABLE, NULL) ;
  prj->RP2->BitMap = AllocBitMap(Xplane, Yplane, prj->wb->RastPort.BitMap->Depth, BMF_CLEAR|BMF_DISPLAYABLE, NULL) ;
  tmpbitmap        = AllocRaster(Xplane, Yplane) ;
  prj->RP2->TmpRas = (struct TmpRas *) InitTmpRas(prj->tmpras, tmpbitmap, RASSIZE(Xplane, Yplane)) ;
  WaitBlit() ;
  BltBitMapRastPort(prj->wb->RastPort.BitMap, prj->backWin.posX, prj->backWin.posY, prj->RP1, 0, 0, prj->backWin.width, prj->backWin.height, 0xc0) ;
 

}

void free_bitmap(idWin * prj) {
  if (prj->tmpras) FreeVec(prj->tmpras) ;
  if (tmpbitmap) FreeRaster(tmpbitmap, Xplane, Yplane) ;
  if (prj->RP1 && prj->RP1->BitMap) FreeBitMap(prj->RP1->BitMap) ;
  if (prj->RP2 && prj->RP2->BitMap) FreeBitMap(prj->RP2->BitMap) ;
  if (prj->RP1) FreeVec(prj->RP1) ;
  if (prj->RP2) FreeVec(prj->RP2) ;
  prj->RP1 = prj->RP2 = NULL ;
  
}

