
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include "gdifb.h"


/******************************************************************************/


typedef unsigned  char  u8;
typedef unsigned short  u16;
typedef unsigned   int  u32;


#define BLACK 0x00000000
#define WHITE 0x00ffffff
#define RED   0x000000ff
#define GREEN 0x0000ff00
#define BLUE  0x00ff0000



/******************************************************************************/


void draw_pixel(int x, int y, int color)
{
	gdifb_pixel(x, y, color);
}


void draw_hline(int y, int x1, int x2, int color)
{
	gdifb_line(x1, y, x2, y, color);
}


void draw_vline(int x, int y1, int y2, int color)
{
	gdifb_line(x, y1, x, y2, color);
}


void draw_rect(int x1, int y1, int x2, int y2, int color)
{
	gdifb_rect(x1, y1, x2, y2, color);
}


void draw_box(int x1, int y1, int x2, int y2, int color)
{
	gdifb_box(x1, y1, x2, y2, color);
}

/******************************************************************************/


#include "sfont.h"
#include "sfont16.h"
#include "font50.h"
#include "font66.h"

const u8 *font_list[6] = {
	sfont,
	sfont16,
	F_DSEG7_50,
	F_DSEG7_66,
};

const u8 font_bt[] = {
	0x08, 0x08, 0x0f, 0x00, 0x00,
	0x10, 0x18, 0x14, 0x92, 0x51, 0x32, 0x14, 0x18,
	0x14, 0x32, 0x51, 0x92, 0x14, 0x18, 0x10,
};

const u8 *current_font = (u8*)sfont;

int select_font(int id)
{
	current_font = font_list[id];
	return 0;
}


static const u8 *find_font(const u8 *font, int ucs)
{
	int total = *(u16*)font;
	int i;

	for(i=0; i<total; i++){
		if(*(u16*)(font+2+i*4+0)==ucs){
			int offset = *(u16*)(font+2+i*4+2);
			//printf("  %04x at %04x\n", ucs, offset);
			return font+offset;
		}
	}

	return NULL;
}


int fb_draw_font_info(int x, int y, const u8 *font_data, int color)
{
	int r, c;

	int ft_adv = font_data[0];
	int ft_bw = font_data[1];
	int ft_bh = font_data[2];
	int ft_bx = (signed char)font_data[3];
	int ft_by = (signed char)font_data[4];
	int ft_lsize = (ft_bw+7)/8;
	font_data += 5;

	x += ft_bx;
	y += ft_by;

	for (r=0; r<ft_bh; r++) {
		for (c=0; c<ft_bw; c++) {
			int b = font_data[c>>3];
			int mask = 0x80>>(c%8);
			if(b&mask){
				draw_pixel(x+c, y, color);
			}
			mask >>= 1;
		}
		font_data += ft_lsize;
		y += 1;
	}

	return ft_adv;
}


int fb_draw_font(int x, int y, int ucs, int color)
{
	const u8 *font_data = find_font(current_font, ucs);
	if(font_data==NULL){
		printf("fb_draw %04x: not found!\n", ucs);
		return -1;
	}

	return fb_draw_font_info(x, y, font_data, color);
}


static int utf8_to_ucs(char **ustr)
{
	u8 *str = (u8*)*ustr;
	int ucs = 0;

	if(*str==0){
		return 0;
	}else if(*str<0x80){
		*ustr = (char*)str+1;
		return *str;
	}else if(*str<0xe0){
		ucs = ((str[0]&0x1f)<<6) | (str[1]&0x3f);
		*ustr = (char*)str+2;
		return ucs;
	}else{
		ucs = ((str[0]&0x0f)<<12) | ((str[1]&0x3f)<<6) | (str[2]&0x3f);
		*ustr = (char*)str+3;
		return ucs;
	}
}


void draw_text(int x, int y, char *str, int color)
{
	int ch;

	while(1){
		ch = utf8_to_ucs(&str);
		if(ch==0)
			break;
		x += fb_draw_font(x, y, ch, color);
	}
}


/******************************************************************************/

char *wday_str[] = {"日", "一", "二", "三", "四", "五", "六"};

static int wday = 0;


typedef struct {
	int xres, yres;
	int font_char;
	int font_dseg;
	u16 x[8];
	u16 y[8];
}LAYOUT;

// 坐标0: 公历日期
// 坐标1: 蓝牙图标
// 坐标2: 电池图标
// 坐标3: 时间
// 坐标4: 农历日期
// 坐标5: 节气
// 坐标6: 节日
// 坐标7: 上下午

LAYOUT layouts[3] = {
	{212, 104, 0, 2,
		{15, 172, 190,  16,  12,  98, 150, 12},
		{ 6,   7,  14,  27,  82,  82,  82, 44},
	},
	{250, 122, 1, 3,
		{15, 206, 226,  12,  12, 118, 176, 15},
		{ 6,   8,  15,  28,  98,  98,  98, 50},
	},
	{296, 128, 1, 3,
		{15, 246, 268,  30,  12, 140, 220, 15,},
		{ 6,   8,  15,  30, 102, 102, 102, 52,},
	},
};

int current_layout = 0;


static void draw_batt(int x, int y, int level)
{
	int p = level;

	draw_rect(x, y-4, x+14, y+4, BLACK);
	draw_box(x-2, y-1, x-1, y+1, BLACK);

	draw_box(x+12-p, y-2, x+12, y+2, BLACK);
}


void fb_test(void)
{
	LAYOUT *lt = &layouts[current_layout];

	// 显示公历日期
	select_font(lt->font_char);
	char tbuf[64];
	sprintf(tbuf, "%4d年%2d月%2d日 星期%s", 2025, 4, 29, wday_str[wday]);
	draw_text(lt->x[0], lt->y[0], tbuf, BLACK);

	// 显示蓝牙图标
	fb_draw_font_info(lt->x[1], lt->y[1], font_bt, BLACK);

	// 显示电池图标
	draw_batt(lt->x[2], lt->y[2], 9);


	// 显示农历日期(不显示年)
	sprintf(tbuf, "%s月%s日", wday_str[wday+1], wday_str[wday+2]);
	draw_text(lt->x[4], lt->y[4], tbuf, BLACK);

	// 显示节气
	strcpy(tbuf, "小寒");
	draw_text(lt->x[5], lt->y[5], tbuf, BLACK);

	// 显示节日
	strcpy(tbuf, "中秋节");
	draw_text(lt->x[6], lt->y[6], tbuf, BLACK);

	// 使用大字显示时间
	select_font(lt->font_dseg);
	sprintf(tbuf, "%2d:%02d", 12+wday, 31+wday);
	draw_text(lt->x[3], lt->y[3], tbuf, BLACK);

	select_font(lt->font_char);
	draw_text(lt->x[7], lt->y[7], "上午", BLACK);


	wday += 1;
	if(wday==7)
		wday = 0;

}


/******************************************************************************/

int main(int argc, char *argv[])
{
	int i, scr_w, scr_h;

	for(i=0; i<3; i++){
		current_layout = i;
		scr_w = layouts[i].xres;
		scr_h = layouts[i].yres;
		printf("Layout %d: %dx%d\n", i, scr_w, scr_h);

		gdifb_init(scr_w, scr_h);
		draw_box(0, 0, scr_w-1, scr_h-1, WHITE);
		draw_rect(0, 0, scr_w-1, scr_h-1, RED);

		fb_test();

		gdifb_flush();
		gdifb_waitkey();
		gdifb_exit(1);
	}

	return 0;
}


