extern "C" {
  #include <string.h>
  #include <stdlib.h>
  #include <stdio.h>
 }
#include "ogFont.h"
#include "objgfx30.h"

ogBitFont::ogBitFont(void) {
  memset(fontDataIdx,0,sizeof(fontDataIdx));
  memset(charWidthTable,0,sizeof(charWidthTable));
  memset(charHeightTable,0,sizeof(charHeightTable));
  fontData = NULL;
  fontDataSize = 0;
  width = 0;
  height = 0;
  numOfChars = 0;
  startingChar = 0;
  BGColour.red = 0;
  BGColour.green = 0;
  BGColour.blue = 0;
  FGColour.red = 255;
  FGColour.green = 255;
  FGColour.blue = 255;
  return;
} // ogBitFont::ogBitFont

void 
ogBitFont::centerTextX(ogSurface& buf, int32 y, const char * TextString ) {
  int32 x;
  x = ((buf.ogGetMaxX()+1)-textWidth(TextString)) / 2;
  putString(buf,x,y,TextString);
  return;
} // ogBitFont::centerTextX

void 
ogBitFont::justifyText(ogSurface& buf, uInt8 horiz, uInt8 vert, const char * textString) {
  uInt32 x,y;
  if (textString==NULL) return;
  switch (horiz) {
  case LeftText:
    x = 0;
    break;
  case CenterText:
    x = ((buf.ogGetMaxX())-textWidth(textString)) / 2;
    break;
  case RightText:
    x = (buf.ogGetMaxX())-textWidth(textString);
    break;
  default:
    return;
  } // switch

  switch (vert) {
  case TopText:
    y = 0; 
    break;
  case CenterText:
    y = ((buf.ogGetMaxY())-height) / 2;
    break;
  case BottomText:
    y = (buf.ogGetMaxY())-height;
  default: 
    return;
  } // switch
  putString(buf,x,y,textString);
  return;
} // ogBitFont::justifyText

bool 
ogBitFont::load(const char* fontFile) {
  return loadFrom(fontFile,0);
} // ogBitFont::Load

bool 
ogBitFont::save(const char* fontFile) {
  return saveTo(fontFile,0);
} // ogBitFont::save

uInt32
ogBitFont::textWidth(const char * textString) {
  uInt32 size=0;
  if (textString==NULL) return 0;
  while (*textString)
    size+=charWidthTable[(uInt8)*(textString++)];
  return size;
} // ogBitFont::textWidth

void 
ogBitFont::setBGColor(uInt8 r, uInt8 g, uInt8 b) {
  BGColour.red = r;
  BGColour.green = g;
  BGColour.blue = b;
  return;
} // ogBitFont::setBGColor

void 
ogBitFont::setFGColor(uInt8 r, uInt8 g, uInt8 b) {
  FGColour.red = r;
  FGColour.green = g;
  FGColour.blue = b;
  return;
} // ogBitFont::setFGColor

void 
ogBitFont::putString(ogSurface& buf, int32 x, int32 y, const char * textString) {
  char ch;
  if (fontData==NULL) return;
  if (textString==NULL) return;
  if (buf.ogAvail()==false) return;
  buf.ogFillRect(x,y,x+textWidth(textString)-1,y+textHeight(textString)-1,
                 buf.ogRGB(BGColour.red, BGColour.green, BGColour.blue));
  while (*textString) {
    ch = *textString++;
    putChar(buf, x, y, ch);
    x+=charWidthTable[(uInt8)ch];
  } // while
} // ogBitFont::putString

void 
ogBitFont::putChar(ogSurface& buf, int32 x, int32 y, const char ch) {
  uInt32 xx, xcount, ycount;
  uInt8 * offset;
  uInt8 bits = 0;
  uInt32 colour;
  if (fontData==NULL) return;
  if (buf.ogAvail()==false) return;
  if (charWidthTable[(uInt8)ch]!=0) {
    colour = buf.ogRGB(FGColour.red,FGColour.green,FGColour.blue);
    offset=(uInt8 *)(fontData);
    offset+=fontDataIdx[(uInt8)ch];
    for (ycount = 0; ycount<=(uInt32)(height-1); ycount++) {
      xcount = charWidthTable[(uInt8)ch];
      xx = 0;
      do {
        if ((xx & 7)==0) bits = *(offset++);
        if (bits & 128)
          buf.ogSetPixel(x+xx,y+ycount,colour);
        bits+=bits;
        xx++;
      } while (--xcount);
    } // for
  } // if
} // ogBitFont::putChar

bool 
ogBitFont::loadFrom(const char * fontFile, uInt32 offset) {
  FILE * infile;
  ogDPFHeader header;
  uInt32 lresult, size;
  free(fontData);
  infile = fopen(fontFile,"rb");
  fseek(infile,offset,SEEK_SET);
  lresult = fread(&header,sizeof(header),1,infile);
  width = header.width;
  height = header.height;
  numOfChars = header.numOfChars;
  if (numOfChars==0) numOfChars = 256;
  startingChar = header.startingChar;

  memset(fontDataIdx,0,sizeof(fontDataIdx));
  memset(charWidthTable,0,sizeof(charWidthTable));
  memset(charHeightTable,0,sizeof(charHeightTable));
  
  size = ((width+7) / 8)*height;
  fontDataSize = size*numOfChars;

  for (int tmp=startingChar; tmp<=startingChar+numOfChars-1; tmp++) {
    charWidthTable[tmp]=width;
    charHeightTable[tmp]=height;
    fontDataIdx[tmp]=(size*(tmp-startingChar));
  } // for
  fontData = malloc(fontDataSize);
  lresult = fread(fontData,1,fontDataSize,infile);
  fclose(infile);
  return true;
} // ogBitFont::loadFrom

bool
ogBitFont::saveTo(const char *, int32) {
  return false;
} // ogBitFont::saveTo

ogBitFont::~ogBitFont(void) {
  if (fontDataSize) free(fontData);
  return;
} // ogBitFont::~ogBitFont


