#include "xfont.h"

fontK::fontK(char* FontName)
{
  if(NULL==TheDisplay)if(NULL==(TheDisplay=XOpenDisplay("")))
    { cerr << "Can't open display.\n";exit(1);}
  if(NULL==(KFontStruct    =XLoadQueryFont(TheDisplay,FontName)))
    { cerr << form("Can't load font \"%s\".",FontName);exit(1);}

  XChar2b Utsu;Utsu.byte1=0x31;Utsu.byte2=0x35;
  int CharDirection; XCharStruct CharOverAll;
  XTextExtents16(KFontStruct,&Utsu,1,
		 &CharDirection,&CharAscent,&CharDescent,&CharOverAll);
  CharLeft =CharOverAll.lbearing;
  CharRight=CharOverAll.rbearing;
  CharSize=CharLeft+CharRight>CharAscent+CharDescent?
    CharLeft+CharRight:CharAscent+CharDescent;
  Width=(CharSize+1)*17+1;Height=(CharSize+1)*17+1;

  TheBitmap=
    XCreatePixmap(TheDisplay,DefaultRootWindow(TheDisplay),Width,Height,1);
  XGCValues Values;Values.foreground=0;Values.background=0;
  Values.font = KFontStruct->fid;

  TheGC = XCreateGC(TheDisplay,TheBitmap,
		    GCForeground|GCBackground|GCFont,&Values);
  XFillRectangle(TheDisplay,TheBitmap,TheGC,0,0,Width,Height);
  XImage* ImageToPut=XGetImage(TheDisplay,TheBitmap,0,0,Width,Height,0xFFFF,
			       XYPixmap);
  XSetForeground(TheDisplay,TheGC,1);
  for(int I=0;I<0x8;++I)for(int J=0;J<0x10;++J)
    {
      XChar2b KChar;KChar.byte1=0x21;KChar.byte2=I*0x10+J;
      XDrawImageString16(TheDisplay,TheBitmap,TheGC,
			 J*(CharSize+1)+CharSize+1,
			 I*(CharSize+1)+CharSize+1,&KChar,1);
    }
  for(int I=0;I<0x8;++I)for(int J=0;J<0x10;++J)
    {
      XChar2b KChar;KChar.byte1=0x22;KChar.byte2=I*0x10+J;
      XDrawImageString16(TheDisplay,TheBitmap,TheGC,
			 J*(CharSize+1)+CharSize+1,
			 I*(CharSize+1)+(CharSize+1)*9,&KChar,1);
    }
  XImage* ImageToGet=XGetImage(TheDisplay,TheBitmap,0,0,Width,Height,0xFFFF,
			       XYPixmap);
  for(int I=0;I<0x8;++I)for(int J=0;J<0x10;++J)
    {
      switch(I*0x10+J)
	{
	case 0x22: case 0x23:
	  fontTranspose(ImageToGet,ImageToPut,
			J*(CharSize+1)+CharSize+1,
			I*(CharSize+1)+CharSize+1-CharAscent);
	  break;
	case 0x24: case 0x25:
	  fontRTShift  (ImageToGet,ImageToPut,
			J*(CharSize+1)+CharSize+1,
			I*(CharSize+1)+CharSize+1-CharAscent);
	  break;
	case 0x46: case 0x48:
	  fontLBShift  (ImageToGet,ImageToPut,
			J*(CharSize+1)+CharSize+1,
			I*(CharSize+1)+CharSize+1-CharAscent);
	  break;
	case 0x47: case 0x49: 
	  fontRBShift  (ImageToGet,ImageToPut,
			J*(CharSize+1)+CharSize+1,
			I*(CharSize+1)+CharSize+1-CharAscent);
	  break;
	case 0x27: case 0x28: case 0x30: case 0x31: case 0x32: case 0x4a: 
	case 0x4b: case 0x4c: case 0x4d: case 0x4e: case 0x4f: case 0x50: 
	case 0x51: case 0x52: case 0x53: case 0x54: case 0x55: case 0x56:
	case 0x57: case 0x58: case 0x59: case 0x5a: case 0x5b: case 0x5d:
	case 0x5e: case 0x60: case 0x61: case 0x62: case 0x63: case 0x64:
	case 0x65: case 0x66:
	  fontRotate   (ImageToGet,ImageToPut,
			J*(CharSize+1)+CharSize+1,
			I*(CharSize+1)+CharSize+1-CharAscent);
	  break;
	case 0x3c: case 0x3d: case 0x3e: case 0x3f: case 0x40: case 0x41:
	case 0x42: case 0x43: case 0x44: case 0x45: 
	  fontTranspose(ImageToGet,ImageToPut,
			J*(CharSize+1)+CharSize+1,
			I*(CharSize+1)+CharSize+1-CharAscent);
	  break;
	default:
	  fontCopy     (ImageToGet,ImageToPut,
			J*(CharSize+1)+CharSize+1,
			I*(CharSize+1)+CharSize+1-CharAscent);
	}
    }
  for(int I=0;I<0x8;++I)
    for(int J=0;J<0x10;++J)
      {
	if(I*0x10+J>=0x2a && I*0x10+J<=0x6a)
	  fontRotate(ImageToGet,ImageToPut,
		     J*(CharSize+1)+CharSize+1,
		     I*(CharSize+1)+(CharSize+1)*9-CharAscent);
	else
	  fontCopy  (ImageToGet,ImageToPut,
		     J*(CharSize+1)+CharSize+1,
		     I*(CharSize+1)+(CharSize+1)*9-CharAscent);
      }
  XPutImage(TheDisplay,TheBitmap,TheGC,ImageToPut,0,0,0,0,Width,Height);
  XDestroyImage(ImageToGet);XDestroyImage(ImageToPut);
}

void fontK::drawChar(Drawable Dest,GC DestGC,XChar2b KChar,int X,int Y)
{
  if(KChar.byte1==0x21)
    {
      uchar C=KChar.byte2;int I=C>>4;int J=0x000F&C;
      XSetStipple   (TheDisplay,DestGC,TheBitmap);
      XSetFillStyle (TheDisplay,DestGC,FillStippled);
      XSetTSOrigin  (TheDisplay,DestGC,
		     -(J*(CharSize+1)+CharSize+1)+X-1-CharDescent+2,
		     -(I*(CharSize+1)+CharSize+1-CharAscent)+Y);
      XFillRectangle(TheDisplay,Dest,DestGC,
		     X-CharDescent+2,Y,CharSize,CharSize);
    }
  else if(KChar.byte1==0x22)
    {
      uchar C=KChar.byte2;int I=C>>4;int J=0x000F&C;
      XSetStipple   (TheDisplay,DestGC,TheBitmap);
      XSetFillStyle (TheDisplay,DestGC,FillStippled);
      XSetTSOrigin  (TheDisplay,DestGC,
		     -(J*(CharSize+1)+CharSize+1)+X-1-CharDescent+2,
		     -(I*(CharSize+1)+(CharSize+1)*9-CharAscent)+Y);
      XFillRectangle(TheDisplay,Dest,DestGC,X-CharDescent+2,Y,
		     CharSize,CharSize);
    }
  else
    {
      XSetFillStyle(TheDisplay,DestGC,FillSolid);
      XSetFont(TheDisplay,DestGC,KFontStruct->fid);
      XDrawString16
	(TheDisplay,Dest,DestGC,X-CharDescent+2,Y+CharAscent,&KChar,1);
    }
}

void fontK::drawHorString
(Drawable Dest,GC DestGC,XChar2b*KString,int N,int X,int Y)
{
  XSetFillStyle(TheDisplay,DestGC,FillSolid);
  XSetFont(TheDisplay,DestGC,KFontStruct->fid);
  XDrawString16(TheDisplay,Dest,DestGC,X-CharDescent,Y+CharAscent,KString,N);
}

fontA::fontA(char* FontName)
{
  if(NULL==TheDisplay)if(NULL==(TheDisplay=XOpenDisplay("")))
    { cerr << "Can't open display.\n";exit(1);}
  if(NULL==(AFontStruct    =XLoadQueryFont(TheDisplay,FontName)))
    { cerr << form("Can't load font \"%s\".",FontName);exit(1);}
  int CharDirection; XCharStruct CharOverAll;
  XTextExtents(AFontStruct,"W",1,
	       &CharDirection,&CharAscent,&CharDescent,&CharOverAll);
  CharLeft =CharOverAll.lbearing;
  CharRight=CharOverAll.rbearing;
  XTextExtents(AFontStruct,"#{><|/yp",1,
	       &CharDirection,&CharAscent,&CharDescent,&CharOverAll);
  CharSize=CharLeft+CharRight>CharAscent+CharDescent?
    CharLeft+CharRight+10:CharAscent+CharDescent+10;
  Width=CharSize*17;Height=CharSize*17;
  TheBitmap=
    XCreatePixmap(TheDisplay,DefaultRootWindow(TheDisplay),Width,Height,1);
  XGCValues Values;Values.foreground=0;Values.background=0;
  Values.font = AFontStruct->fid;
  TheGC=XCreateGC(TheDisplay,TheBitmap,
		  GCForeground|GCBackground|GCFont,&Values);
  XFillRectangle(TheDisplay,TheBitmap,TheGC,0,0,Width,Height);
  XImage* ImageToPut=XGetImage(TheDisplay,TheBitmap,0,0,Width,Height,0xFFFF,
			       XYPixmap);
  XSetForeground(TheDisplay,TheGC,1);uchar String[2];String[1]='\0';
  for(int I=0;I<0x10;++I) for(int J=0;J<0x10;++J)
    {
      String[0]=I*0x10+J;
      XDrawImageString(TheDisplay,TheBitmap,TheGC,
		       I*CharSize+CharSize,(15-J)*CharSize+CharSize,
		       (char*)String,1);
      }
  XImage* ImageToGet=XGetImage(TheDisplay,TheBitmap,0,0,Width,Height,0xFFFF,
			       XYPixmap);
  for(int X=0;X<Width;++X)for(int Y=0;Y<Height;++Y)
    {
      ulong Pixel= XGetPixel(ImageToGet,X,Y);
      XPutPixel(ImageToPut,Width-Y,X,Pixel);
    }
  XPutImage(TheDisplay,TheBitmap,TheGC,ImageToPut,0,0,0,0,Width,Height);
  XDestroyImage(ImageToGet);XDestroyImage(ImageToPut);
}

void fontA::drawChar(Drawable Dest,GC DestGC,char Ch,int X,int Y)
{
  uchar C=Ch;int I=C>>4;int J=0x000F&C;
  XSetStipple  (TheDisplay,DestGC,TheBitmap);
  XSetFillStyle(TheDisplay,DestGC,FillStippled);
  XSetTSOrigin (TheDisplay,DestGC,
		-(J+1)*CharSize-CharDescent+1+X+2,-(I+1)*CharSize+Y);
  XFillRectangle(TheDisplay,Dest,DestGC,
		 X-CharDescent+2,Y,
		 CharDescent+CharAscent+5,CharLeft+CharRight+5);
}

void fontA::drawHorString
(Drawable Dest,GC DestGC,char* String,int N,int X,int Y)
{
  XSetFillStyle(TheDisplay,DestGC,FillSolid);
  XSetFont(TheDisplay,DestGC,AFontStruct->fid);
  XDrawString(TheDisplay,Dest,DestGC,X-CharDescent+2,Y+CharAscent,String,N);
}

void fontA::drawHorChar(Drawable Dest,GC DestGC,char Ch,int X,int Y)
{
  XSetFillStyle(TheDisplay,DestGC,FillSolid);
  XSetFont(TheDisplay,DestGC,AFontStruct->fid);
  XDrawString(TheDisplay,Dest,DestGC,X-CharDescent+2,Y+CharAscent,&Ch,1);
}

