/* myfonts.cc			letzte Aenderung: 19.2.2021

History:
5.9.2019        Erstellung (RP)
14.9.2019       Font 9x12 erstellt
2.1.2021        Anpassung fuer Zusammenspiel mit otekplot1.h
4.2.2021        Fonts 14x18 und 14x20 angefuegt (provisorisch, noch schoener zeichnen)
11.2.2021       Fehlerkorrektur und Vereinfachungen

Einteilung in Fonttypen:
Typ  Grund-Aufbau           x-Pixel                      y-Pixel                    Leerbits
 1   Zeilenweiser Aufbau    Bits von links nach rechts   Bytes von oben nach unten  rechts
 2   Zeilenweiser Aufbau    Bits von links nach rechts   Bytes von oben nach unten  links
 3   Zeilenweiser Aufbau    Bits von rechts nach links   Bytes von oben nach unten  rechts
 4   Zeilenweiser Aufbau    Bits von rechts nach links   Bytes von oben nach unten  links
 5   Zeilenweiser Aufbau    Bits von links nach rechts   Bytes von unten nach oben  rechts
 6   Zeilenweiser Aufbau    Bits von links nach rechts   Bytes von unten nach oben  links
 7   Zeilenweiser Aufbau    Bits von rechts nach links   Bytes von unten nach oben  rechts
 8   Zeilenweiser Aufbau    Bits von rechts nach links   Bytes von unten nach oben  links
 9   Spaltenweiser Aufbau   Bytes von links nach rechts  Bits von oben nach unten   unten
10   Spaltenweiser Aufbau   Bytes von links nach rechts  Bits von oben nach unten   oben
11   Spaltenweiser Aufbau   Bytes von links nach rechts  Bits von unten nach oben   unten
12   Spaltenweiser Aufbau   Bytes von links nach rechts  Bits von unten nach oben   oben
13   Spaltenweiser Aufbau   Bytes von rechts nach links  Bits von oben nach unten   unten
14   Spaltenweiser Aufbau   Bytes von rechts nach links  Bits von oben nach unten   oben
15   Spaltenweiser Aufbau   Bytes von rechts nach links  Bits von unten nach oben   unten
16   Spaltenweiser Aufbau   Bytes von rechts nach links  Bits von unten nach oben   oben

*/

#include "myfonts.h"

//TODO: optional nicht alle Fonts laden?
// Default-Fonts:
uchar myfont6x8[256*8] = {
#include "myfont6x8.h"
};
uchar myfont9x12[256*24] = {
#include "myfont9x12.h"
};
uchar myfont12x16[256*32] = {
#include "myfont12x16.h"
};
uchar myfont14x18[256*36] = {
#include "myfont14x18.h"
};
uchar myfont14x20[256*40] = {
#include "myfont14x20.h"
};

/* z.B. so im Hauptprogramm benutzen:
static Font font_tiny(myfont6x8,      6,  8, 1,  8);
static Font font_small(myfont9x12,    9, 12, 1, 24);
static Font font_normal(myfont12x16, 12, 16, 1, 32);
static Font font_big(myfont14x18,    14, 18, 1, 36);
static Font font_biger(myfont14x20,  14, 20, 1, 40);
int main() {
 ...
 aktfont = &font_normal; //aktueller_font
 aktfont->init(dx,dy,1,1); //dx,dy sollte Pixelgroesse in User-Koordinaten sein
 aktfont->itextsize(12,16);
 ...
}
*/

Font default_font(myfont12x16, 12, 16, 1, 32);
Font *aktfont= &default_font; //Zeiger auf aktuellen Font

/**************************** Hauptteil *******************************/
bool Font::missingInit()
{
 if(user_dx>0 && user_dy>0) return false;
 fprintf(stderr,"Error: missing call of Font::init()\n");
 return true;
}

int Font::font_aendern(const char *font)
{
 if(strcmp(font,"12x16")==0)     {neuerFont(myfont12x16, 12, 16, 1, 32);}
 else if(strcmp(font,"6x8")==0)  {neuerFont(myfont6x8,    6,  8, 1,  8);}
 else if(strcmp(font,"9x12")==0) {neuerFont(myfont9x12,   9, 12, 1, 24);}
 //TODO: die folgenden Fonts noch editieren:
 else if(strcmp(font,"14x18")==0) {neuerFont(myfont14x18, 14, 18, 1, 36);}
 else if(strcmp(font,"14x20")==0) {neuerFont(myfont14x20, 14, 20, 1, 40);}
 //TODO: weitere Fonts erstellen
 else
  {
   printf("font_aendern(): Font \"%s\" nicht gefunden.\n",font);
   printf("bisher nur diese Fonts vorhanden: 6x8, 9x12, 12x16, 14x18, 14x20\n");
   return 0;
  }
 scalx=scaly=1;
 return hy; //Fonthoehe in Pixel
}

int Font::itextsize(int b,int h,const char *font,int style)
{
 //printf("itextsize(b=%d,h=%d, font, style=%d)\n",b,h,style);//test
 if(missingInit()) return 0;
 if(font!=NULL)
  {
   if(font_aendern(font)==0) return hy*scaly; //bei Fehler alter Font behalten
  }
 if(style!=0) printf("itextsize() style noch nicht veraenderbar\n");
 //Skalierfaktoren berechnen:
 scalx = (int)(b/bx+0.5); if(scalx<1) scalx=1;
 scaly = (int)(h/hy+0.5); if(scaly<1) scaly=1;
 //tatsaechliche Zeichengroesse in Pixel:
 b = bx*scalx;
 h = hy*scaly;
 //Zeichengroesse in User-Koordinaten:
 schrift_breite = b*user_dx;
 schrift_hoehe  = h*user_dy;
 return h;
}

double Font::textsize(double b,double h,const char *font,int style)
{
 //printf("textsize(b=%f,h=%f, font, style=%d)\n",b,h,style);//test
 if(missingInit()) return 0;
 if(font!=NULL)
  {
   if(font_aendern(font)==0) return schrift_hoehe; //bei Fehler alter Font behalten
  }
 //Skalierfaktoren berechnen:
 scalx = (int)(b/user_dx/bx+0.5); if(scalx<1) scalx=1;
 scaly = (int)(h/user_dy/hy+0.5); if(scaly<1) scaly=1;
 if(style!=0) printf("textsize() style noch nicht veraenderbar\n");
 //tatsaechliche Zeichengroesse in Pixel:
 int ib = bx*scalx;
 int ih = hy*scaly;
 //Zeichengroesse in User-Koordinaten:
 schrift_breite = ib*user_dx;
 schrift_hoehe  = ih*user_dy;
 return schrift_hoehe;
}

uchar *bitlesen(uchar *pfont,int i,int j,int *maske,int bx,int hy,int typ)
{
 // i kann Werte von 0 bis bx-1 haben, 0 ist Spalte ganz links
 // j kann Werte von 0 bis hy-1 haben, 0 ist oberste Zeile
 // bx ist Fontbreite, hy ist Fonthoehe, typ ist Fonttyp
 uchar leerbits;
 uchar *p1=NULL;
 int bytesprozeile=1,bytesprospalte=1,nbits=0;
 int bx1=bx-1, hy1=hy-1;
 if(typ<=8) {bytesprozeile = (bx+7)/8;  leerbits = 8-bx%8;}
 else       {bytesprospalte = (hy+7)/8; leerbits = 8-hy%8;}
 //static int testflag=0;
 //if(testflag==0) {printf("bytesprozeile=%d prospalte=%d  typ=%d\n",bytesprozeile,bytesprospalte,typ); testflag++;}//test
 //if(typ!=1)//test
 // {printf("bitlesen(pfont,i=%d,j=%d,bx=%d,hy=%d,typ=%d)\n",i,j,bx,hy,typ);//test
 //  printf("bytesprozeile=%d\n",bytesprozeile);//test
 // }
 if(leerbits==8) leerbits=0;
 if(typ<1 || typ>16)
  {
   fprintf(stderr,"Error: in bitlesen() unknown Fonttyp %d - defaulting to Typ 3\n",typ);
   typ=3;
  }
 switch(typ)
  {
   //       Typ  Grund-Aufbau           x-Pixel                      y-Pixel                    Leerbits
   case 1:// 1   Zeilenweiser Aufbau    Bits von links nach rechts   Bytes von oben nach unten  rechts
     p1 = &pfont[bytesprozeile*j+i/8];
     nbits = 7-i%8;
     break;
   case 2:// 2   Zeilenweiser Aufbau    Bits von links nach rechts   Bytes von oben nach unten  links
     p1 = &pfont[bytesprozeile*j+(i+leerbits)/8]; //noch testen
     nbits = 7-(i+leerbits)%8; //noch testen
     break;
   case 3:// 3   Zeilenweiser Aufbau    Bits von rechts nach links   Bytes von oben nach unten  rechts
     p1 = &pfont[bytesprozeile*j+(bx1-i+leerbits)/8];
     nbits = (i+leerbits)%8;
     break;
   case 4:// 4   Zeilenweiser Aufbau    Bits von rechts nach links   Bytes von oben nach unten  links
     p1 = &pfont[bytesprozeile*j+(bx1-i)/8];
     nbits = i%8;
     break;
   case 5:// 5   Zeilenweiser Aufbau    Bits von links nach rechts   Bytes von unten nach oben  rechts
     p1 = &pfont[bytesprozeile*(hy1-j)+i/8]; //noch testen
     nbits = 7-i%8; //noch testen
     break;
   case 6:// 6   Zeilenweiser Aufbau    Bits von links nach rechts   Bytes von unten nach oben  links
     p1 = &pfont[bytesprozeile*(hy1-j)+(i+leerbits)/8]; //noch testen
     nbits = 7-(i+leerbits)%8; //noch testen
     break;
   case 7:// 7   Zeilenweiser Aufbau    Bits von rechts nach links   Bytes von unten nach oben  rechts
     p1 = &pfont[bytesprozeile*(hy1-j)+(bx1-i+leerbits)/8]; //noch testen
     nbits = (i+leerbits)%8; //noch testen
     break;
   case 8:// 8   Zeilenweiser Aufbau    Bits von rechts nach links   Bytes von unten nach oben  links
     p1 = &pfont[bytesprozeile*(hy1-j)+(bx1-i)/8]; //noch testen
     nbits = i%8; //noch testen
     break;
   //       Typ  Grund-Aufbau           x-Pixel                      y-Pixel                    Leerbits
  case  9:// 9   Spaltenweiser Aufbau   Bytes von links nach rechts  Bits von oben nach unten   unten
     p1 = &pfont[bytesprospalte*i+j/8]; //noch testen
     nbits = j%8+leerbits; //noch testen
     break;
  case 10://10   Spaltenweiser Aufbau   Bytes von links nach rechts  Bits von oben nach unten   oben
     p1 = &pfont[bytesprospalte*i+(j+leerbits)/8]; //noch testen
     nbits = 7-(j+leerbits)%8; //noch testen
     break;
  case 11://11   Spaltenweiser Aufbau   Bytes von links nach rechts  Bits von unten nach oben   unten
     p1 = &pfont[bytesprospalte*i+(hy1-j+leerbits)/8]; //noch testen
     nbits = (j+leerbits)%8; //noch testen
     break;
  case 12://12   Spaltenweiser Aufbau   Bytes von links nach rechts  Bits von unten nach oben   oben
     p1 = &pfont[bytesprospalte*i+(hy1-j)/8]; //noch testen
     nbits = j%8+leerbits; //noch testen
     break;
  case 13://13   Spaltenweiser Aufbau   Bytes von rechts nach links  Bits von oben nach unten   unten
     p1 = &pfont[bytesprospalte*(bx1-i)+j/8]; //noch testen
     nbits = 7-j%8; //noch testen
     break;
  case 14://14   Spaltenweiser Aufbau   Bytes von rechts nach links  Bits von oben nach unten   oben
     p1 = &pfont[bytesprospalte*(bx1-i)+(j+leerbits)/8]; //noch testen
     nbits = 7-(j+leerbits)%8; //noch testen
     break;
  case 15://15   Spaltenweiser Aufbau   Bytes von rechts nach links  Bits von unten nach oben   unten
     p1 = &pfont[bytesprospalte*(bx1-i)+(hy1-j+leerbits)/8]; //noch testen
     nbits = (j+leerbits)%8; //noch testen
     break;
  case 16://16   Spaltenweiser Aufbau   Bytes von rechts nach links  Bits von unten nach oben   oben
     p1 = &pfont[bytesprospalte*(bx1-i)+(hy1-j)/8]; //noch testen
     nbits = j%8; //noch testen
     break;
  }
 *maske = (1<<nbits);
 return p1;
}

bool Font::bitgesetzt(uchar *pf,int i,int j)  //i=Zaehler in x-Richtung, j=y-Richtung
{
 int maske,c;
 uchar *p;
 p = bitlesen(pf, i, j, &maske, bx, hy, typ);
 c = *p;
 //printf("Testpunkt bitgesetzt(): c=0x%02X maske=0x%02X\n",c,maske);//test
 return (c&maske)!=0;
}

void Font::zeichne_zeichen(double x0,double y0,uchar zeichen,bool punktflag)
{
 int i,j;
 double x,y,x1;
 uchar *pf;
 double dy=schrift_hoehe/hy;
 double dx=schrift_breite/bx;
 //bool testflag=(bytesprozeichen!=32);//test
 //if(testflag) printf("zeichen=%c bytesprozeichen=%d\n",zeichen,bytesprozeichen);//test
 pf = &pfont[zeichen*bytesprozeichen];
 //if(testflag) {for(int k=0;k<bytesprozeichen;k++) printf("0x%02X ",pf[k]); printf("\n");}//test
 x1=x0;
 for(x=x1,i=0; i<bx; i++,x+=dx)
  for(y=y0+(hy-1)*dy,j=0; j<hy; j++,y-=dy)
   {
    if(bitgesetzt(pf,i,j))
     {
      if(punktflag) tek_punkt(x,y);
      else fillbox(x,y,x+dx,y+dy);
     }
   }
}

void Font::schrift(double x0,double y0,const char *text,double winkel,bool utf8flag)
{
 //TODO: utf8flag auswerten
 if(utf8flag) printf("Warnung in Font::schrift() - kann noch kein UTF8 auswerten\n");
 double x=x0;
 bool punktflag = (scaly==1 && scalx==1);//setzen falls Pixelgroesse der Schrift nur 1 Punkt gross ist
 //if(punktflag) printf("schrift() punktflag=true text=\"%s\"\n",text);//test
 if(winkel==0)
  {
   if(hintergrundfarbe!=0)
    {
     //printf("Font::schrift(.. \"%s\" ..) mit Hintergrund 0x%X\n",text,hintergrundfarbe);//test
     double x2 = x0 + strlen(text)*schrift_breite;
     double y2 = y0 + schrift_hoehe;
     zwert_decrement();
     color(hintergrundfarbe);
     fillbox(x0,y0,x2,y2);
     zwert_decrement();
     color(vordergrundfarbe);
    }
   else
    {
     //printf("Font::schrift(.. \"%s\" ..) ohne Hintergrund\n",text);//test
    }
   for(int i=0;text[i]!=0;i++)
    {
     zeichne_zeichen(x,y0,text[i],punktflag);
     x += schrift_breite;
    }
  }
 else
  {
   //TODO
   printf("schrift() mit winkel=%f noch nicht programmiert. Bisher nur winkel=0 moeglich.\n",winkel);
  }
}

void Font::ischrift(int x0,int y0,const char *text,double winkel,bool utf8flag)
{
 double x,y;
 koordpix2user(x0,y0,&x,&y);
 schrift(x,y,text,winkel,utf8flag);
}

/*
void wprintf(double x,double y,const char *cstr,int p1,int p2=0)
{
 char str[200];
 sprintf(str,cstr,p1,p2);
 schrift(x,y,str);
}
*/

void Font::color(uint32_t color)
{
 //printf("Testpunkt Font::color(0x%X)\n",color);//test
 int r,g,b;
 r = color&0xFF;
 g = (color>>8)&0xFF;
 b = (color>>16)&0xFF;
 rgbcolor(r,g,b);
}
