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

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

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

CSF1_GlyphsData_t g_tCSF1GlyphsData;

typedef enum {
	C2S_COMMAND_END = 0,
	C2S_COMMAND_PENDOWN = 1,
	C2S_COMMAND_PENUP = 2,
	C2S_COMMAND_SINGLEVECTOR = 8,
	C2S_COMMAND_MULTIVECTOR = 9,
	C2S_COMMAND_VARTICAL = 14,
} C2S_Command_t;

typedef struct C2S_Pos {
	signed int X;
	signed int Y;
} C2S_Pos_t;

typedef struct C2S_CommandOnly {
	C2S_Command_t Command;
} C2S_CommandOnly_t;

typedef struct C2S_Vector {
	C2S_Command_t Command;
	unsigned int PosesCount;
	C2S_Pos_t Poses[120];
} C2S_Vector_t;

typedef struct C2S_Vartical {
	C2S_Command_t Command;
	C2S_Pos_t Pos;
} C2S_Vartical_t;

typedef union C2S_Item {
	C2S_CommandOnly_t CommandOnly;
	C2S_Vector_t Vector;
	C2S_Vartical_t Vartical;
} C2S_Item_t;

typedef struct C2S_Shape {
	unsigned int Code;
	unsigned int Code8;
	unsigned int CodeJ;
	unsigned int Bytes;
	unsigned int ItemsCount;
	C2S_Item_t Items[120];
	char Name[32];
} C2S_Shape_t;

typedef struct C2S_ShapesData {
	unsigned int ShapesCount;
	C2S_Shape_t Shapes[10000];
} C2S_ShapesData_t;

C2S_ShapesData_t g_tShapesData;

void CSF1ToShape(C2S_ShapesData_t* o_ptShapesData, const CSF1_GlyphsData_t* i_ptCSF1GlyphsData) {
	CSF1_Glyph_t* ptCSF1Glyph;
	C2S_Shape_t* ptShape;
	CSF1_Item_t* ptCSF1Item;
	unsigned int uiVectorCount;
	unsigned int uiCount1, uiCount2;
	int iLastDrawX, iLastDrawY;
	int iFromX, iFromY;
	int iToX, iToY;
	unsigned int uiVector, uiPen;
	int res;

	ptShape = &(o_ptShapesData->Shapes[0]);
	ptShape->Code = 0xA;
	ptShape->ItemsCount = 0;
	/* pen up */
	ptShape->Items[ptShape->ItemsCount].CommandOnly.Command = C2S_COMMAND_PENUP;
	ptShape->ItemsCount++;
	/* vartical start */
	ptShape->Items[ptShape->ItemsCount].CommandOnly.Command = C2S_COMMAND_VARTICAL;
	ptShape->ItemsCount++;
	ptShape->Items[ptShape->ItemsCount].Vector.Command = C2S_COMMAND_SINGLEVECTOR;
	ptShape->Items[ptShape->ItemsCount].Vector.Poses[0].X = -64;
	ptShape->Items[ptShape->ItemsCount].Vector.Poses[0].Y = 0;
	ptShape->Items[ptShape->ItemsCount].Vector.PosesCount = 1;
	ptShape->ItemsCount++;
	/* move */
	ptShape->Items[ptShape->ItemsCount].Vector.Command = C2S_COMMAND_SINGLEVECTOR;
	ptShape->Items[ptShape->ItemsCount].Vector.Poses[0].X = 0;
	ptShape->Items[ptShape->ItemsCount].Vector.Poses[0].Y = -32;
	ptShape->Items[ptShape->ItemsCount].Vector.PosesCount = 1;
	ptShape->ItemsCount++;
	/* end */
	ptShape->Items[ptShape->ItemsCount].CommandOnly.Command = C2S_COMMAND_END;
	ptShape->ItemsCount++;
	ptShape->Bytes = 9;

	for(uiCount1 = 0; uiCount1 < i_ptCSF1GlyphsData->GlyphsCount; uiCount1++) {
		ptCSF1Glyph = (CSF1_Glyph_t*)&(i_ptCSF1GlyphsData->Glyphs[uiCount1]);
		ptShape = &(o_ptShapesData->Shapes[uiCount1 + 1]);

		ptShape->CodeJ = ptCSF1Glyph->JIS;
		ptShape->Code = 0;
		ptShape->Code8 = 0;
		ptShape->CodeJ = ptCSF1Glyph->JIS;
		strcpy(ptShape->Name, "noname");

		res = ConvertCode(ptShape->CodeJ, &(ptShape->Code), &(ptShape->Code8));

		iLastDrawX = 0;
		iLastDrawY = 0;
		iFromX = 0;
		iFromY = 0;
		iToX = 0;
		iToY = 0;
		uiVector = 0;
		uiPen = 0;

		/* pen up */
		ptShape->Items[ptShape->ItemsCount].CommandOnly.Command = C2S_COMMAND_PENUP;
		ptShape->ItemsCount++;

		if(ptShape->CodeJ >= 0x00 && ptShape->CodeJ <= 0x7F) {
			/* vartical start */
			ptShape->Items[ptShape->ItemsCount].CommandOnly.Command = C2S_COMMAND_VARTICAL;
			ptShape->ItemsCount++;
			ptShape->Items[ptShape->ItemsCount].Vector.Command = C2S_COMMAND_SINGLEVECTOR;
			ptShape->Items[ptShape->ItemsCount].Vector.Poses[0].X = -8;
			ptShape->Items[ptShape->ItemsCount].Vector.Poses[0].Y = -32;
			ptShape->Items[ptShape->ItemsCount].Vector.PosesCount = 1;
			ptShape->ItemsCount++;
		} else if(ptShape->CodeJ >= 0x1A20 && ptShape->CodeJ <= 0x1A7F) {
			/* vartical start */
			ptShape->Items[ptShape->ItemsCount].CommandOnly.Command = C2S_COMMAND_VARTICAL;
			ptShape->ItemsCount++;
			ptShape->Items[ptShape->ItemsCount].Vector.Command = C2S_COMMAND_SINGLEVECTOR;
			ptShape->Items[ptShape->ItemsCount].Vector.Poses[0].X = -8;
			ptShape->Items[ptShape->ItemsCount].Vector.Poses[0].Y = -32;
			ptShape->Items[ptShape->ItemsCount].Vector.PosesCount = 1;
			ptShape->ItemsCount++;
		} else {
			/* vartical start */
			ptShape->Items[ptShape->ItemsCount].CommandOnly.Command = C2S_COMMAND_VARTICAL;
			ptShape->ItemsCount++;
			ptShape->Items[ptShape->ItemsCount].Vector.Command = C2S_COMMAND_SINGLEVECTOR;
			ptShape->Items[ptShape->ItemsCount].Vector.Poses[0].X = -16;
			ptShape->Items[ptShape->ItemsCount].Vector.Poses[0].Y = -32;
			ptShape->Items[ptShape->ItemsCount].Vector.PosesCount = 1;
			ptShape->ItemsCount++;
		}

		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:
					/* continuas vector */
					if(iLastDrawX == iFromX && iLastDrawY == iFromY) {
						ptShape->Items[ptShape->ItemsCount].Vector.Command = C2S_COMMAND_MULTIVECTOR;
						ptShape->Items[ptShape->ItemsCount].Vector.Poses[ptShape->Items[ptShape->ItemsCount].Vector.PosesCount].X = (signed int)(ptCSF1Item->Val) - iFromX;
						ptShape->Items[ptShape->ItemsCount].Vector.Poses[ptShape->Items[ptShape->ItemsCount].Vector.PosesCount].Y = 0;
						ptShape->Items[ptShape->ItemsCount].Vector.PosesCount++;
					/* start vector */
					} else {
						/* end vector */
						if(uiVector) {
							if(ptShape->Items[ptShape->ItemsCount].Vector.PosesCount > 1) {
								ptShape->Items[ptShape->ItemsCount].Vector.Command = C2S_COMMAND_MULTIVECTOR;
								ptShape->Items[ptShape->ItemsCount].Vector.Poses[ptShape->Items[ptShape->ItemsCount].Vector.PosesCount].X = 0;
								ptShape->Items[ptShape->ItemsCount].Vector.Poses[ptShape->Items[ptShape->ItemsCount].Vector.PosesCount].Y = 0;
								ptShape->Items[ptShape->ItemsCount].Vector.PosesCount++;
							}
							ptShape->ItemsCount++;
						}
						if(uiPen) {
							/* pen up */
							ptShape->Items[ptShape->ItemsCount].CommandOnly.Command = C2S_COMMAND_PENUP;
							ptShape->ItemsCount++;
						}
						/* move */
						ptShape->Items[ptShape->ItemsCount].Vector.Command = C2S_COMMAND_SINGLEVECTOR;
						ptShape->Items[ptShape->ItemsCount].Vector.Poses[0].X = iFromX - iLastDrawX;
						ptShape->Items[ptShape->ItemsCount].Vector.Poses[0].Y = iFromY - iLastDrawY;
						ptShape->Items[ptShape->ItemsCount].Vector.PosesCount = 1;
						ptShape->ItemsCount++;
						/* pen down */
						ptShape->Items[ptShape->ItemsCount].CommandOnly.Command = C2S_COMMAND_PENDOWN;
						ptShape->ItemsCount++;
						/* draw vector */
						ptShape->Items[ptShape->ItemsCount].Vector.Command = C2S_COMMAND_SINGLEVECTOR;
						ptShape->Items[ptShape->ItemsCount].Vector.Poses[0].X = (signed int)(ptCSF1Item->Val) - iFromX;
						ptShape->Items[ptShape->ItemsCount].Vector.Poses[0].Y = 0;
						ptShape->Items[ptShape->ItemsCount].Vector.PosesCount = 1;
					}
					iFromX = (signed int)(ptCSF1Item->Val);
					iLastDrawX = iFromX;
					iToX = iFromX;
					iLastDrawY = iFromY;
					uiVector = 1;
					uiPen = 1;
					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:
					/* continuas vector */
					if(iLastDrawX == iFromX && iLastDrawY == iFromY) {
						ptShape->Items[ptShape->ItemsCount].Vector.Command = C2S_COMMAND_MULTIVECTOR;
						ptShape->Items[ptShape->ItemsCount].Vector.Poses[ptShape->Items[ptShape->ItemsCount].Vector.PosesCount].X = iToX - iFromX;
						ptShape->Items[ptShape->ItemsCount].Vector.Poses[ptShape->Items[ptShape->ItemsCount].Vector.PosesCount].Y = (signed int)(ptCSF1Item->Val) - iFromY;
						ptShape->Items[ptShape->ItemsCount].Vector.PosesCount++;
					/* start vector */
					} else {
						/* end vector */
						if(uiVector) {
							if(ptShape->Items[ptShape->ItemsCount].Vector.PosesCount > 1) {
								ptShape->Items[ptShape->ItemsCount].Vector.Command = C2S_COMMAND_MULTIVECTOR;
								ptShape->Items[ptShape->ItemsCount].Vector.Poses[ptShape->Items[ptShape->ItemsCount].Vector.PosesCount].X = 0;
								ptShape->Items[ptShape->ItemsCount].Vector.Poses[ptShape->Items[ptShape->ItemsCount].Vector.PosesCount].Y = 0;
								ptShape->Items[ptShape->ItemsCount].Vector.PosesCount++;
							}
							ptShape->ItemsCount++;
						}
						if(uiPen) {
							/* pen up */
							ptShape->Items[ptShape->ItemsCount].CommandOnly.Command = C2S_COMMAND_PENUP;
							ptShape->ItemsCount++;
						}
						/* move */
						ptShape->Items[ptShape->ItemsCount].Vector.Command = C2S_COMMAND_SINGLEVECTOR;
						ptShape->Items[ptShape->ItemsCount].Vector.Poses[0].X = iFromX - iLastDrawX;
						ptShape->Items[ptShape->ItemsCount].Vector.Poses[0].Y = iFromY - iLastDrawY;
						ptShape->Items[ptShape->ItemsCount].Vector.PosesCount = 1;
						ptShape->ItemsCount++;
						/* pen down */
						ptShape->Items[ptShape->ItemsCount].CommandOnly.Command = C2S_COMMAND_PENDOWN;
						ptShape->ItemsCount++;
						/* draw vector */
						ptShape->Items[ptShape->ItemsCount].Vector.Command = C2S_COMMAND_SINGLEVECTOR;
						ptShape->Items[ptShape->ItemsCount].Vector.Poses[0].X = iToX - iFromX;
						ptShape->Items[ptShape->ItemsCount].Vector.Poses[0].Y = (signed int)(ptCSF1Item->Val) - iFromY;
						ptShape->Items[ptShape->ItemsCount].Vector.PosesCount = 1;
					}
					iFromX = iToX;
					iLastDrawX = iFromX;
					iFromY = (signed int)(ptCSF1Item->Val);
					iLastDrawY = iFromY;
					uiVector = 1;
					uiPen = 1;
					break;
			}
		}
		if(ptShape->Items[ptShape->ItemsCount].Vector.Command == C2S_COMMAND_SINGLEVECTOR) {
			if(ptShape->Items[ptShape->ItemsCount].Vector.Poses[0].X != 0 || ptShape->Items[ptShape->ItemsCount].Vector.Poses[0].Y != 0) {
				ptShape->ItemsCount++;
			}
		} else if(ptShape->Items[ptShape->ItemsCount].Vector.Command == C2S_COMMAND_MULTIVECTOR) {
			ptShape->Items[ptShape->ItemsCount].Vector.Poses[ptShape->Items[ptShape->ItemsCount].Vector.PosesCount].X = 0;
			ptShape->Items[ptShape->ItemsCount].Vector.Poses[ptShape->Items[ptShape->ItemsCount].Vector.PosesCount].Y = 0;
			ptShape->Items[ptShape->ItemsCount].Vector.PosesCount++;
			ptShape->ItemsCount++;
		}

		/* pen up */
		ptShape->Items[ptShape->ItemsCount].CommandOnly.Command = C2S_COMMAND_PENUP;
		ptShape->ItemsCount++;

		if(ptShape->CodeJ >= 0x00 && ptShape->CodeJ <= 0x7F) {
			/* shape end */
			ptShape->Items[ptShape->ItemsCount].Vector.Command = C2S_COMMAND_SINGLEVECTOR;
			ptShape->Items[ptShape->ItemsCount].Vector.Poses[0].X = 16 - iFromX;
			ptShape->Items[ptShape->ItemsCount].Vector.Poses[0].Y = 0 - iFromY;
			ptShape->Items[ptShape->ItemsCount].Vector.PosesCount = 1;
			ptShape->ItemsCount++;

			/* vartical end */
			ptShape->Items[ptShape->ItemsCount].CommandOnly.Command = C2S_COMMAND_VARTICAL;
			ptShape->ItemsCount++;
			ptShape->Items[ptShape->ItemsCount].Vector.Command = C2S_COMMAND_SINGLEVECTOR;
			ptShape->Items[ptShape->ItemsCount].Vector.Poses[0].X = -8;
			ptShape->Items[ptShape->ItemsCount].Vector.Poses[0].Y = 0;
			ptShape->Items[ptShape->ItemsCount].Vector.PosesCount = 1;
			ptShape->ItemsCount++;
		} else if(ptShape->CodeJ >= 0x1A20 && ptShape->CodeJ <= 0x1A7F) {
			/* shape end */
			ptShape->Items[ptShape->ItemsCount].Vector.Command = C2S_COMMAND_SINGLEVECTOR;
			ptShape->Items[ptShape->ItemsCount].Vector.Poses[0].X = 16 - iFromX;
			ptShape->Items[ptShape->ItemsCount].Vector.Poses[0].Y = 0 - iFromY;
			ptShape->Items[ptShape->ItemsCount].Vector.PosesCount = 1;
			ptShape->ItemsCount++;

			/* vartical end */
			ptShape->Items[ptShape->ItemsCount].CommandOnly.Command = C2S_COMMAND_VARTICAL;
			ptShape->ItemsCount++;
			ptShape->Items[ptShape->ItemsCount].Vector.Command = C2S_COMMAND_SINGLEVECTOR;
			ptShape->Items[ptShape->ItemsCount].Vector.Poses[0].X = -8;
			ptShape->Items[ptShape->ItemsCount].Vector.Poses[0].Y = 0;
			ptShape->Items[ptShape->ItemsCount].Vector.PosesCount = 1;
			ptShape->ItemsCount++;
		} else {
			/* shape end */
			ptShape->Items[ptShape->ItemsCount].Vector.Command = C2S_COMMAND_SINGLEVECTOR;
			ptShape->Items[ptShape->ItemsCount].Vector.Poses[0].X = 32 - iFromX;
			ptShape->Items[ptShape->ItemsCount].Vector.Poses[0].Y = 0 - iFromY;
			ptShape->Items[ptShape->ItemsCount].Vector.PosesCount = 1;
			ptShape->ItemsCount++;

			/* vartical end */
			ptShape->Items[ptShape->ItemsCount].CommandOnly.Command = C2S_COMMAND_VARTICAL;
			ptShape->ItemsCount++;
			ptShape->Items[ptShape->ItemsCount].Vector.Command = C2S_COMMAND_SINGLEVECTOR;
			ptShape->Items[ptShape->ItemsCount].Vector.Poses[0].X = -16;
			ptShape->Items[ptShape->ItemsCount].Vector.Poses[0].Y = 0;
			ptShape->Items[ptShape->ItemsCount].Vector.PosesCount = 1;
			ptShape->ItemsCount++;
		}

		/* end */
		ptShape->Items[ptShape->ItemsCount].CommandOnly.Command = C2S_COMMAND_END;
		ptShape->ItemsCount++;

		ptShape->Bytes = 0;
		for(uiCount2 = 0; uiCount2 < ptShape->ItemsCount; uiCount2++) {
			switch(ptShape->Items[uiCount2].CommandOnly.Command) {
				case C2S_COMMAND_END:
				case C2S_COMMAND_PENUP:
				case C2S_COMMAND_PENDOWN:
				case C2S_COMMAND_VARTICAL:
					ptShape->Bytes++;
					break;
				case C2S_COMMAND_SINGLEVECTOR:
					ptShape->Bytes += 3;
					break;
				case C2S_COMMAND_MULTIVECTOR:
					ptShape->Bytes += ptShape->Items[uiCount2].Vector.PosesCount * 2 + 1;
					break;
			}
		}
	}
	o_ptShapesData->ShapesCount = i_ptCSF1GlyphsData->GlyphsCount;
}

void OutputSHP(const C2S_ShapesData_t* i_ptShapesData) {
	unsigned int uiCount1, uiCount2, uiCount3;
	C2S_Shape_t* ptShape;
	C2S_Item_t* ptItem;

	printf(";;\n");
	printf(";; kst32b.shp - kst32b\n");
	printf(";;\n");
	printf(";; Copyright 2014 by AZO <typesylph@gmail.com> (convert).\n");
	printf(";; Author Saka.N <Saka.N.06@b3.mnx.ne.jp> (Proj.KST32B_2).\n");
	printf(";;\n");
	printf("\n");
	printf("*UNIFONT,6,kst32b\n");
	printf("32,0,2,0,0,0\n");
	printf("\n");

	for(uiCount1 = 0; uiCount1 < i_ptShapesData->ShapesCount; uiCount1++) {
		ptShape = (C2S_Shape_t*)&(i_ptShapesData->Shapes[uiCount1]);

		printf("; UTF-16:%04X UTF-8:%06X JIS:%04X Bytes:%d Items:%d\n", ptShape->Code, ((ptShape->Code8 & 0xFF) << 16) + (((ptShape->Code8 >> 8) & 0xFF) << 8) + ((ptShape->Code8 >> 16) & 0xFF), ptShape->CodeJ, ptShape->Bytes, ptShape->ItemsCount);

		if(ptShape->Code == 0) {
			printf("; ");
		}
		printf("*0%04X,%d,%s\n", ptShape->Code, ptShape->Bytes, ptShape->Name);

		for(uiCount2 = 0; uiCount2 < ptShape->ItemsCount; uiCount2++) {
			ptItem = &(ptShape->Items[uiCount2]);

			if(ptShape->Code == 0) {
				printf("; ");
			}
			switch(ptItem->CommandOnly.Command) {
				case C2S_COMMAND_PENUP:
				case C2S_COMMAND_PENDOWN:
				case C2S_COMMAND_VARTICAL:
				case C2S_COMMAND_END:
					printf("%d\n", ptItem->CommandOnly.Command);
					break;
				case C2S_COMMAND_SINGLEVECTOR:
					printf("%d,(%d,%d)\n", ptItem->Vector.Command, ptItem->Vector.Poses[0].X, ptItem->Vector.Poses[0].Y);
					break;
				case C2S_COMMAND_MULTIVECTOR:
					printf("%d", ptItem->Vector.Command);
					for(uiCount3 = 0; uiCount3 < ptItem->Vector.PosesCount; uiCount3++) {
						printf(",%d,%d", ptItem->Vector.Poses[uiCount3].X, ptItem->Vector.Poses[uiCount3].Y);
					}
					printf("\n");
					break;
			}
		}
		printf("\n");
	}
}

int main(int i_iArgc, char* i_lstrArgv[]) {
	LoadKST32B(&g_tCSF1GlyphsData);
	CSF1ToShape(&g_tShapesData, &g_tCSF1GlyphsData);
	OutputSHP(&g_tShapesData);
	return 0;
}		

