/* csf12lff.c */
/* Programed by AZO */
/* This code is free. At Your Own Risk. */

/* Build: gcc csf1.c kst32b.c csf12lff.c -o csf12lff */
/* PreRun: chmod +x csf12lff */
/* Run: ./csf12lff > kst32b.lff */

#include "csf1.h"
#include "kst32b.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

CSF1_GlyphsData_t g_tCSF1GlyphsData;

typedef struct C2L_Vector {
	signed int FromX;
	signed int FromY;
	signed int ToX;
	signed int ToY;
} C2L_Vector_t;

typedef struct C2L_Glyph {
	unsigned int Code;
	unsigned int VectorsCount;
	C2L_Vector_t Vectors[155];
} C2L_Glyph_t;

typedef struct C2L_GlyphData {
	unsigned int GlyphsCount;
	C2L_Glyph_t Glyphs[10000];
} C2L_GlyphsData_t;

C2L_GlyphsData_t g_tGlyphsData;

void CSF1ToVector(C2L_GlyphsData_t* o_ptGlyphsData, const CSF1_GlyphsData_t* i_ptCSF1GlyphsData) {
	signed int iFromX, iFromY, iToX;
	CSF1_Glyph_t* ptCSF1Glyph;
	C2L_Glyph_t* ptGlyph;
	CSF1_Item_t* ptCSF1Item;
	unsigned int uiVectorCount;
	unsigned int uiCount1, uiCount2;

	memset(&g_tGlyphsData, 0, sizeof(C2L_GlyphsData_t));

	for(uiCount1 = 0; uiCount1 < i_ptCSF1GlyphsData->GlyphsCount; uiCount1++) {
		ptCSF1Glyph = (CSF1_Glyph_t*)&(i_ptCSF1GlyphsData->Glyphs[uiCount1]);
		ptGlyph = &(o_ptGlyphsData->Glyphs[uiCount1]);

		ptGlyph->Code = ptCSF1Glyph->JIS;

		uiVectorCount = 0;
		iFromX = 0;
		iFromY = 0;
		iToX = 0;

		for(uiCount2 = 0; uiCount2 < ptCSF1Glyph->ItemCount; uiCount2++) {
			ptCSF1Item = &(ptCSF1Glyph->Items[uiCount2]);

			switch(ptCSF1Item->Action) {
				case CSF1_INIT:
				case CSF1_TERM:
					break;
				case CSF1_MOVE_X:
					iFromX = (signed int)(ptCSF1Item->Val);
					iToX = iFromX;
					break;
				case CSF1_DRAW_X:
					ptGlyph->Vectors[uiVectorCount].FromX = iFromX;
					ptGlyph->Vectors[uiVectorCount].FromY = iFromY;
					ptGlyph->Vectors[uiVectorCount].ToX = (signed int)(ptCSF1Item->Val);
					ptGlyph->Vectors[uiVectorCount].ToY = iFromY;
					uiVectorCount++;
					iFromX = (signed int)(ptCSF1Item->Val);
					iToX = iFromX;
					break;
				case CSF1_NEXT_X:
					iToX = (signed int)(ptCSF1Item->Val);
					break;
				case CSF1_MOVE_Y:
					iFromY = (signed int)(ptCSF1Item->Val);
					break;
				case CSF1_DRAW_Y:
					ptGlyph->Vectors[uiVectorCount].FromX = iFromX;
					ptGlyph->Vectors[uiVectorCount].FromY = iFromY;
					ptGlyph->Vectors[uiVectorCount].ToX = iToX;
					ptGlyph->Vectors[uiVectorCount].ToY = (signed int)(ptCSF1Item->Val);
					uiVectorCount++;
					iFromX = iToX;
					iFromY = (signed int)(ptCSF1Item->Val);
					break;
			}
		}
		ptGlyph->VectorsCount = uiVectorCount;
	}
	o_ptGlyphsData->GlyphsCount = i_ptCSF1GlyphsData->GlyphsCount;
}

void PrintGlyphs(const C2L_GlyphsData_t* i_ptGlyphsData) {
	unsigned int uiCount1, uiCount2;
	C2L_Glyph_t* ptGlyph;
	C2L_Vector_t* ptVector;

	/* Print output */
	for(uiCount1 = 0; uiCount1 < i_ptGlyphsData->GlyphsCount; uiCount1++) {
		ptGlyph = (C2L_Glyph_t*)&(i_ptGlyphsData->Glyphs[uiCount1]);
		printf("Code : 0x%08X / Items : %d\n", ptGlyph->Code, ptGlyph->VectorsCount);
		for(uiCount2 = 0; uiCount2 < ptGlyph->VectorsCount; uiCount2++) {
			ptVector = &(ptGlyph->Vectors[uiCount2]);
			printf("from %d,%d to %d,%d\n", ptVector->FromX, ptVector->FromY, ptVector->ToX, ptVector->ToY);
		}
		printf("\n");
	}
	printf("%d glyphs. done.\n", i_ptGlyphsData->GlyphsCount);
}

void OutputLFF(const C2L_GlyphsData_t* i_ptGlyphsData) {
	unsigned int uiCount1, uiCount2;
	C2L_Glyph_t* ptGlyph;
	C2L_Vector_t* ptVector;
	unsigned int unicode16;
	unsigned int unicode8;
	char str[16];
	unsigned int uiEnableGlyph = 0;
	unsigned int uiDisableGlyph = 0;
	int res;

	printf("# Format:            LibreCAD Font 1\n");
	printf("# Creator:           AZO\n");
	printf("# Version:           master\n");
	printf("# Name:              KST32B\n");
	printf("# Name:              Japanese\n");
	printf("# Encoding:          UTF-8\n");
	printf("# LetterSpacing:     3\n");
	printf("# WordSpacing:       6.75\n");
	printf("# LineSpacingFactor: 1\n");
	printf("# Created:           2014-12-06\n");
	printf("# Last modified:     2014-12-06\n");
	printf("# Author:            AZO <typesylph@gmail.com> (convert)\n");
	printf("# Author:            Saka.N <Saka.N.06@b3.mnx.ne.jp> (Proj.KST32B_2)\n");
	printf("# License:           GPL v2 or later, KST32B\n");
	printf("\n");

	for(uiCount1 = 0; uiCount1 < i_ptGlyphsData->GlyphsCount; uiCount1++) {
		ptGlyph = (C2L_Glyph_t*)&(i_ptGlyphsData->Glyphs[uiCount1]);

		res = ConvertCode(ptGlyph->Code, &unicode16, &unicode8);

		if(res) {
			if(ptGlyph->Code < 0x100) {
				printf("# JIS    : %02x\n", ptGlyph->Code & 0xFF);
			} else {
				printf("# JIS    : %02x %02x\n", (ptGlyph->Code >> 8) & 0xFF, ptGlyph->Code & 0xFF);
			}
			if(unicode16 < 0x100) {
				printf("# UTF-16 : %02x\n", unicode16 & 0xFF);
			} else {
				printf("# UTF-16 : %02x %02x\n", (unicode16 >> 8) & 0xFF, unicode16 & 0xFF);
			}
			if(unicode8 < 0x100) {
				printf("# UTF-8  : %02x\n", unicode8 & 0xFF);
			} else {
				if(unicode8 < 0x10000) {
					printf("# UTF-8  : %02x %02x\n", unicode8 & 0xFF, (unicode8 >> 8) & 0xFF);
				} else {
					printf("# UTF-8  : %02x %02x %02x\n", unicode8 & 0xFF, (unicode8 >> 8) & 0xFF, (unicode8 >> 16) & 0xFF);
				}
			}

			sprintf(str, "[%04x]", unicode16);
			str[6] = ' ';
			if(unicode8 < 0x10000) {
				str[7] = (unicode8      ) & 0xFF;
				str[8] = (unicode8 >>  8) & 0xFF;
				str[9] = '\0';
			} else {
				str[7] = (unicode8      ) & 0xFF;
				str[8] = (unicode8 >>  8) & 0xFF;
				str[9] = (unicode8 >> 16) & 0xFF;
				str[10] = '\0';
			}
			printf(str);
			printf("\n");
		} else {
			printf("# JIS    : %02x %02x\n", (ptGlyph->Code >> 8) & 0xFF, ptGlyph->Code & 0xFF);
		}

		for(uiCount2 = 0; uiCount2 < ptGlyph->VectorsCount; uiCount2++) {
			ptVector = &(ptGlyph->Vectors[uiCount2]);
			if(!res) {
				printf("# ");
			}
			printf("%.2f,%.2f;%.2f,%.2f\n", (double)(ptVector->FromX)/32*10, (double)(ptVector->FromY)/32*10, (double)(ptVector->ToX)/32*10, (double)(ptVector->ToY)/32*10);
		}
		printf("\n");

		if(res) {
			uiEnableGlyph++;
		} else {
			uiDisableGlyph++;
		}
	}
	printf("# Enable glyphs  : %d\n", uiEnableGlyph);
	printf("# Disable glyphs : %d\n", uiDisableGlyph);
}

int main(int i_iArgc, char* i_lstrArgv[]) {
	LoadKST32B(&g_tCSF1GlyphsData);
	CSF1ToVector(&g_tGlyphsData, &g_tCSF1GlyphsData);
	OutputLFF(&g_tGlyphsData);
	return 0;
}		

