最近分析字型檔格式,是時候搭個稍微過得去的架構來整理一下代碼。
主要處理幾個需求:
1,跨平台。
2,只分析TrueType格式
3,解析幾個表:cmap(編碼,圖元索引映射),glyf(僅取資料),os/2表。繪製圖元指令有時候就再看看。
初步的設計:
1,使用者管理幾個主要的資料Memory, Face。
2,最底層是system,封裝一些與平台相關的api;倒數第二層是stream,主要封裝一些對資料流的操作,同級的是資料層,真正有意義的資料,儲存關於字型相關的資訊,以及資料流,都是由使用者來管理。最上層是對各個表的解析。
3,主要提供資料的操作,不提供資料的管理,管理由使用者處理。
底層system初步代碼如下:
TTSystem.h
#include "TrueTypeConfig.h"<br />#include "TrueTypeData.h"<br />#define TT_MEM_COPY(dest, src, length) /<br />memcpy(dest, src, length)<br />void TT_Close_Stream_Free(TT_Stream stream);<br />void TT_Close_Stream_Munmap(TT_Stream stream);<br />TT_RESULT<br />TT_Open_Stream(TT_Stream stream, const char* filename);<br />TT_RESULT<br />TT_Close_Stream(TT_Stream stream);
TTSystem.c
#include <sys/types.h><br />#include <unistd.h><br />#include <sys/mman.h><br />#include <fcntl.h><br />#include <sys/stat.h><br />#include <stdlib.h><br />#include <stdio.h><br />#include "TrueTypeSystem.h"<br />TT_RESULT<br />TT_Open_Stream(TT_Stream stream, const char* filename)<br />{<br />if (stream == NULL || filename == NULL)<br />return TT_ERROR;<br />int file = open(filename, O_RDONLY);<br />if (file < 0)<br />return TT_ERROR;<br />struct stat stat_buff;<br />if (fstat(file, &buff) < 0)<br />{<br />close(file);<br />return TT_ERROR;<br />}<br />stream->size = buff.st_size;<br />stream->pos = 0;<br />stream->head = (unsigned char*)mmap(NULL,<br />stream->size,<br />PROT_READ,<br />MAP_FILE | MAP_PRIVATE,<br />file,<br />0);<br />if ((long)stream->head > 0)<br />{<br />stream->close = TT_Close_Stream_Munmap;<br />}<br />else<br />{<br />stream->close = TT_Close_Stream_Free;<br />stream->head = (unsigned char*)malloc(stream->size);<br />if (stream->head == NULL)<br />{<br />close(file);<br />return TT_ERROR;<br />}<br />ssize_t total_buff_size = 0;<br />do<br />{<br />ssize_t curr_read_buff_size = 0;<br />curr_read_buff_size = read(file,<br /> stream->head + total_buff_size,<br /> stream->size - total_buff_size);<br />if (curr_read_buff_size <= 0)<br />{<br />close(file);<br />stream->close(stream);<br />return TT_ERROR;<br />}<br />total_buff_size += curr_read_buff_size;<br />}while ((TT_LONG)total_buff_size != stream->size);<br />}<br />close(file);<br />return TT_OK;<br />}</p><p>TT_RESULT<br />TT_Close_Stream(TT_Stream stream)<br />{<br />if (stream == NULL || stream->close == NULL)<br />return TT_ERROR;<br />stream->close(stream);<br />return TT_OK;<br />}</p><p>void TT_Close_Stream_Free(TT_Stream stream)<br />{<br />if (stream != NULL)<br />free(stream->head);<br />}<br />void TT_Close_Stream_Munmap(TT_Stream stream)<br />{<br />if (stream != NULL)<br />munmap((MUNMAP_ARG_CAST)stream->head, stream->size);<br />}<br />
資料流操作初步代碼如下:
TTStream.h
//xuexuankr<br />//2011.2.5 8:27PM<br />//bytes stream operator<br />#include "TrueTypeConfig.h"<br />#include "TrueTypeData.h"</p><p>//next bytes in buff<br />#define BUFF_NEXT_SHORT(buff) /<br />(buff += 2)<br />#define BUFF_NEXT_USHORT(buff) /<br />(buff += 2)<br />#define BUFF_NEXT_LONG(buff) /<br />(buff += 4)<br />#define BUFF_NEXT_ULONG(buff) /<br />(buff += 4)</p><p>//get bytes from stream<br />#define STREAM_GET_USHORT(value, a, b) /<br />(value = ( (TT_USHORT)(a) << 8 ) | /<br /> (TT_USHORT)(b) )<br />#define STREAM_GET_SHORT(value, a, b) /<br />(value = ( (TT_SHORT)(a) << 8) | /<br /> (TT_SHORT)(b))<br />#define STREAM_GET_ULONG(value, a, b, c, d) /<br />(value = ( (TT_ULONG)(a) << 24) | /<br /> ( (TT_ULONG)(b) << 16) | /<br /> ( (TT_ULONG)(c) << 8) | /<br /> (TT_ULONG)(d))<br />#define STREAM_GET_LONG(value, a, b, c, d) /<br />(value = ( (TT_LONG)(a) << 24) | /<br /> ( (TT_LONG)(b) << 16) | /<br /> ( (TT_LONG)(c) << 8) | /<br /> (TT_LONG)(d) )</p><p>//bytes operation<br />TT_Result<br />TT_Stream_Read(TT_Stream stream,<br />TT_BYTE* buff,<br />TT_LONG length);<br />TT_Result<br />TT_Stream_Seek(TT_Stream stream,<br />TT_LONG pos);<br />
TTStream.c
#include <math.h><br />#include "TrueTypeStream.h"<br />TT_RESULT<br />TT_Stream_Read(TT_Stream stream,<br /> TT_BYTE* buff,<br /> TT_LONG length)<br />{<br />if (stream == NULL || buff == NULL)<br />return TT_ERROR;<br />if (length > stream->size)<br />return TT_ERROR;<br />TT_ULONG buff_rest_len = stream->size - stream->pos;<br />if (length > buff_rest_len)<br />return TT_ERROR;<br />TT_MEM_COPY(buff, stream->head + stream->pos, length);<br />stream->pos += length;<br />return TT_OK;<br />}<br />TT_RESULT<br />TT_Stream_Seek(TT_Stream stream, TT_LONG pos)<br />{<br />if (stream == NULL)<br />return TT_ERROR;<br />if (stream->size < (stream->pos + pos) || (stream->pos + pos) < stream->head)<br />return TT_ERROR;<br />stream->pos += pos;<br />return TT_OK;<br />}<br />
目前只有TT_Stream 的資料
TTData.h
#include "TrueTypeConfig.h"<br />typedef void (*TT_Close_Stream)(TT_Stream stream);<br />typedef struct<br />{<br />TT_BYTE* head;<br />TT_LONG curr_pos;<br />TT_LONG size;<br />TT_Close_Stream close;<br />}TT_StreamRec;<br />typedef TT_StreamRec* TT_Stream;<br />