子驱动程序模式在稍有程序规模的C项目中大量应用
- Uinx一切皆文件
- Unix/Linux
- MiniGUI识别、应用不同的图片格式
注:一个统一的接口,下面有有不同的实现内容。
子驱动程序模式的一般实现套路
- 一套聚类接口
- 一些公共数据组成的抽象对象(数据结构)
- 一组函数指针组成的操作集(数据结构)
- 针对不同子类的操作集实现
struct _file_obj;
typedef struct _file_obj file_obj;
struct _file_ops {
file_obj *open(void *pathname_buf, size_t size, const char xx);
ssize_t read(file_obj *file, void *buf, size_t count);
ssize_t write(file_obj *file, const void *buf, size_t count);
off_t lseek(file_obj *file, off_t offset, int whence);
void close(file_obj *file);
};
struct _FILE;
typedef struct _FILE FILE;
struct _FILE{
};
struct _file_obj{
void* buf;
size_t size;
unsigned int flags;
off_t rw_pos;
};
static file_obj *mem_open(void *buf, size_t size, const char xxx)
{
...
}
static struct _file_ops mem_file_ops = {
open: mem_open;
...
}
FILE *fmemopen(void *buf, size_t size, const char *mode)
{
FILE *file = NULL;
file_obj *obj = mem_open(buf,size,mode);
if(obj)
{
file = calloc(1, sizeof(FILE));
file.obj = obj;
file.ops = file_file_ops;
}
return file;
}
进一步考虑
- STDIO是带有缓冲区功能的,缓冲区信息应该在FILE中维护还是在file_obj中维护?
- 当前读写位置在什么地方维护?
- 子驱动程序设计的关键点
- 抽象对象的数据结构如何确定?
- 操作集如何取舍?
正确区分机制和策略
- 机制:需要提供什么功能
- 策略:如何使用这些功能
- 以STDIO实现为例:
- 带有缓冲区支持的格式化输入输出属于使用策略,对不同类型的文件对象是一样的。
- 文件操作集提供的就是机制,符合最小的完备集合原则。
注:锤子的机制:【把】长、轻、韧(增加力矩,便于挥动);【头】硬,重,造型(便于敲击,释放力量); 锤子的策略:1. 可以用来砸钉子;2. 可以用来转圈着砸,安装于机器上; 3,可以放到机器人手里,然后给机器人下指令; 4,可以只小幅度挥动;5.等等; 综上,可见机制是更适合底层驱动实现,策略更符合上层应用实现。所以,对抽象的数据结构,操作集合都可依据此做判断,是放到驱动层,还是应用层。
MINIGUI中的逻辑字体
- 现代图形系统中文字的显示过程:
- 字符串解码取出一个个字符。
- 如果包含有复杂书写(如阿拉伯、希伯来、印度语系文字),需要做双向排版处理。
- 字符到字型:如果含有复杂书写文字,需要做字符成型(shaping)处理,比如组合字符问题。
- 从字体文件中获取自型信息(点阵或矢量)。
- 交由图形系统渲染字型到指定的缓冲区位置。
PLOGFONT CreateLogFontByName(const char* font_name);
void GUIAPI DestroyLogFont (PLOGFONT log_font);
PLONGFONT GUIAPI SelectFont (HDC hdc, PLONGFONT log_font);
int GUIAPI TextOutLen (HDC hdc, int x, int y,const char* spText, int xxx);
......
- 抽象字符集
- 转化为unicode
- 排版操作
struct _DEVFONT;
typedef struct _DEVFONT DEVFONT;
typedef struct _LOGFONT{
char* type;
char* family;
char* charset;
DWORD32 style;
int size;
int rotation;
....
unsigned short scales[MAXNR_DEVFONTS];
DEVFONT* devfonts[MAXNR_DEVFONTS];
}LOGFONT;
struct DEVFONT
{
char name[ MAX +1 ];
...
FONTOPS* font_ops;
CHARSETOPS* charset_ops;
....
}
struct _CHARSETOPS
{
int nr_chars;
int bytes_maxlen_char;
const char* name;
....
int (*len_first_char)(const unsigned char * mstr, int mst,xxx);
Achar32(*get_char_value)(const unsigned char * xxxx, xxxx);
}
|