/*----------------------------------------------------------------------------*

                                 __                 $RCSfile: render.c,v $
                                / /                 $Revision: 1.3 $
       _____ ______ ______ ____/ /______ _____      $Date: 93/01/30 00:59:54 $
      / ___// ____// __  // __  // ____// ___/      $Author: tf $
     / /   / __/_ / / / // /_/ // __/_ / /          $Locker:  $
    /_/   /_____//_/ /_//_____//_____//_/           $State: Exp $


          (c) Copyright 1992-93 Tobias Ferber, All Rights Reserved.

 *----------------------------------------------------------------------------*/

#include <exec/types.h>
#include <graphics/gfxbase.h>
#include <graphics/gfx.h>
#include <graphics/rastport.h>
#include <graphics/text.h>
#include <hardware/blit.h>
#include <libraries/diskfont.h>
#include <stdio.h>

ULONG *DiskfontBase= (ULONG *)NULL;
struct GfxBase *GfxBase= (struct GfxBase *)NULL;

/*#define DEBUG*/
#define HYPERSLOWSMART

#ifdef DEBUG
#include <intuition/intuition.h>
struct IntuitionBase *IntuitionBase= (struct IntuitionBase *)NULL;

static void dbug_bmap(struct BitMap *bmap, SHORT width)
{
  static struct NewWindow nw= { 0,0,0,0,1,0,
                                MOUSEBUTTONS,
                                BORDERLESS|SUPER_BITMAP,
                                NULL,NULL,NULL,NULL,NULL,
                                0,0,0,0,
                                WBENCHSCREEN };
  if(IntuitionBase= (struct IntuitionBase *)OpenLibrary("intuition.library",0L))
  { struct Window *w;
    nw.Width=width;
    nw.Height=bmap->Rows;
    nw.BitMap=bmap;
    if(w= (struct Window *)OpenWindow(&nw))
    { struct IntuiMessage *imsg;
      BOOL done= FALSE;
      while(!done)
      { Wait(1L<<w->UserPort->mp_SigBit);
        while(imsg= (struct IntuiMessage *)GetMsg(w->UserPort))
        { done= (imsg->Class == MOUSEBUTTONS);
          ReplyMsg(imsg);
        }
      }
      CloseWindow(w);
    }
    CloseLibrary(IntuitionBase);
  }
}
#endif /* DEBUG */

#ifdef HYPERSLOWSMART
extern UBYTE SmartieTable[256];

static UBYTE Smartie(struct RastPort *rp, UWORD w,
                                          UWORD h,
                                          UWORD x,
                                          UWORD y)
{ UBYTE magic=0;
  if(ReadPixel(rp,x,y)==0) return(' ');
  if(y>0)
  { if(x>0) if(ReadPixel(rp,x-1,y-1)!=0) magic |= (1<<7);
    if(ReadPixel(rp,x,y-1)!=0) magic |= (1<<6);
    if(x<w) if(ReadPixel(rp,x+1,y-1)!=0) magic |= (1<<5);
  }
  if(x>0) if(ReadPixel(rp,x-1,y)!=0) magic |= (1<<4);
  if(x<w) if(ReadPixel(rp,x+1,y)!=0) magic |= (1<<3);
  if(y<h)
  { if(x>0) if(ReadPixel(rp,x-1,y+1)!=0) magic |= (1<<2);
    if(ReadPixel(rp,x,y+1)!=0) magic |= (1<<1);
    if(x<w) if(ReadPixel(rp,x+1,y+1)!=0) magic |= (1<<0);
  }
  return SmartieTable[magic];
}

#endif /* HYPERSLOWSMART */

/*
 * Render a banner out of a font's bitmap
 */

int render_banner(char *s,       /* text to render */
                  char *fname,   /* font name */
                  int fsize,     /* font size */
                      fstyle,    /* font style: 0x00 = normal
                                  *             0x01 = underlined
                                  *             0x02 = bold
                                  *             0x04 = italic */
                  int aspect,    /* 0 = horizontal (x) aspect
                                  * 1 = vertical   (y) aspect 
                                  * 2 = horizontal (x) aspect + smart */
                  char set,      /* character used for set pixels */
                  char unset )   /* character used for unset pixels */
{
  char *str= (char *)NULL; /* don't print the banner until we havn't
                            * closed all the system stuff...
                            */
  if(GfxBase= (struct GfxBase *)OpenLibrary("graphics.library",0L))
  { if(DiskfontBase= (ULONG *)OpenLibrary("diskfont.library",0L))
    { struct TextFont *tf;
      struct TextAttr ta;

      ta.ta_Name= fname;
      ta.ta_YSize= fsize;
      ta.ta_Style= fstyle;
      ta.ta_Flags= FPF_DISKFONT;

      tf= (struct TextFont *)OpenDiskFont(&ta);
      if(tf)
      { struct RastPort rp;
        struct BitMap bmap;
        int tl;   /* text length in raster dots */
        InitRastPort(&rp);
        SetFont(&rp,tf);
        tl= TextLength(&rp,s,strlen(s));
        if(bmap.Planes[0]= (PLANEPTR)AllocRaster(tl,tf->tf_YSize))
        {
          /* InitBitMap always sets the #of bytes per row to an even
           * value. I hope that AllocRaster() is smart enough to allocate
           * enough memory also if tl>>3 is odd...
           */

          InitBitMap(&bmap,1L,tl,tf->tf_YSize);
          rp.BitMap= &bmap;
          SetAPen(&rp,1L);
          SetBPen(&rp,0L);
          SetDrMd(&rp,JAM2); /* => no need for BltClear() */
          SetRast(&rp,0L);
          Move(&rp,0L,rp.TxBaseline);
          Text(&rp,s,strlen(s));

#ifdef DEBUG
          printf("bpr=%d, tl=%d, strlen(s)=%d\n",
            bmap.BytesPerRow,tl,strlen(s));
          dbug_bmap(&bmap,tl);
#endif /* DEBUG */

          if(aspect==0)
          { if(str= (char *)malloc((tl+1)*tf->tf_YSize+1))
            { int x,y,b,w,c; /* x,y,bit,width and character counter */
              char *cp= str;
              UBYTE *pp= (UBYTE *)bmap.Planes[0];
              for(y=0;y<tf->tf_YSize;y++)
              { for(x=0,w=0,c=0;x<bmap.BytesPerRow;x++,pp++)
                { for(b=7;b>=0 && w<tl;b--,w++)
                  { if(set=='\0' && w>=TextLength(&rp,s,c+1))
                      c++; /* There is a problem in italic mode... */
                    *cp++= (*pp&(1<<b)) ? ((set=='\0') ? s[c] : set) : unset;
                  }
                }
                *cp++='\n';
              }
              *cp='\0';
            }
            else fatal("not enough memory!");
          }
          else if(aspect==1)
          { if(str= (char *)malloc(1+tl*(tf->tf_YSize+1)))
            { int x,y,b,w,c; /* x,y,bit,width and character counter */
              char *cp= str;
              UBYTE *pp= (UBYTE *)bmap.Planes[0];
              for(x=0,w=0,c=0;x<bmap.BytesPerRow && w<tl;x++,pp++)
              { for(b=7;b>=0 && w<tl;b--,w++)
                { if(set=='\0' && w>=TextLength(&rp,s,c+1))
                    c++;
                  for(y=tf->tf_YSize-1;y>=0;y--)
                    *cp++ = (pp[y*bmap.BytesPerRow]&(1<<b)) ?
                            ((set=='\0')?s[c]:set) : unset;
                  *cp++='\n';
                }
              }
              *cp='\0';
            }
            else fatal("not enough memory!");
          }

#ifdef HYPERSLOWSMART
          else if(aspect==2)
          { if(str= (char *)malloc((tl+1)*tf->tf_YSize+1))
            { int x,y,b,w,c; /* x,y,bit,width and character counter */
              char *cp= str;
              UBYTE *pp= (UBYTE *)bmap.Planes[0];
              for(y=0;y<tf->tf_YSize;y++)
              { for(x=0,w=0,c=0;x<bmap.BytesPerRow;x++,pp++)
                { for(b=7;b>=0 && w<tl;b--,w++)
                  { if(set=='\0' && w>=TextLength(&rp,s,c+1))
                      c++; /* There is a problem in italic mode... */
                    *cp++= Smartie(&rp,tl,tf->tf_YSize,w,y);
                  }
                }
                *cp++='\n';
              }
              *cp='\0';
            }
            else fatal("not enough memory!");
          }
#endif /* HYPERSLOWSMART */

          FreeRaster(bmap.Planes[0],tl,tf->tf_YSize);
        }
        else fatal("not enough graphics memory");
        CloseFont(tf);
      }
      else fatal("unable to open your font");
      CloseLibrary(DiskfontBase);
    }
    else fatal("can't open diskfont.library");
    CloseLibrary(GfxBase);
  }
  else fatal("can't open graphics.library");
  if(str)
  { puts(str);
    free(str);
  }
  return 0;
}
