ref: acc2272a84dfe957c57c26768144b7a9ddd5da27
dir: /otfpriv.h/
struct Range {
int start;
int len;
int prevoff;
Range *par;
};
#define rchr(s) (be ? ((s)[0]<<8 | (s)[1]) : ((s)[1]<<8 | (s)[0]))
static u8int mark[] = {0x00, 0x00, 0xc0, 0xe0, 0xf0};
static int
utf16to8(u8int *o, int osz, u8int *s, int sz)
{
u32int c, c2;
int i, wr, j, be;
i = 0;
be = 1;
if(s[0] == 0xfe && s[1] == 0xff)
i += 2;
else if(s[0] == 0xff && s[1] == 0xfe){
be = 0;
i += 2;
}
for(; i < sz-1 && osz > 1;){
c = rchr(&s[i]);
i += 2;
if(c >= 0xd800 && c <= 0xdbff && i < sz-1){
c2 = rchr(&s[i]);
if(c2 >= 0xdc00 && c2 <= 0xdfff){
c = 0x10000 | (c - 0xd800)<<10 | (c2 - 0xdc00);
i += 2;
}else
return -1;
}else if(c >= 0xdc00 && c <= 0xdfff)
return -1;
if(c < 0x80)
wr = 1;
else if(c < 0x800)
wr = 2;
else if(c < 0x10000)
wr = 3;
else
wr = 4;
osz -= wr;
if(osz < 1)
break;
o += wr;
for(j = wr; j > 1; j--){
*(--o) = (c & 0xbf) | 0x80;
c >>= 6;
}
*(--o) = (u8int)c | mark[wr];
o += wr;
}
*o = 0;
return i;
}
static char *
strtoutf8(Otf *o, u8int *in, int sz)
{
char *s;
// FIXME this is not sufficient, obviously - need more platform/encoding handling
if(o->platformID == 0 || (o->platformID == 3 && o->encodingID == 1)){
s = malloc(sz/2+1);
utf16to8((u8int*)s, sz/2+1, in, sz);
}else{
s = malloc(sz+1);
memcpy(s, in, sz);
s[sz] = 0;
}
return s;
}
Otf *
otfopen(char *path)
{
Otf *o;
Biobuf *f;
if((f = Bopen(path, OREAD)) == nil)
return nil;
if((o = calloc(1, sizeof(*o))) == nil){
werrstr("no memory");
Bterm(f);
}else{
o->f = f;
}
return o;
}
void
otfclose(Otf *o)
{
if(o == nil)
return;
// FIXME traverse and free everything
free(o);
}
static int
otfpushrange(Otf *o, int off, int len)
{
Range *r;
int x;
r = nil;
if(o->r != nil){
if(len < 0)
len = o->r->len - off;
if(len < 0 || off+len > o->r->len){
werrstr("range overflow (len %d) by %d bytes", len, off+len - o->r->len);
goto err;
}
off += o->r->start;
}else if(len < 0){
len = 0x7fffffff;
}
if((r = malloc(sizeof(*r))) == nil){
werrstr("no memory");
goto err;
}
r->par = o->r;
r->start = off;
r->len = len;
r->prevoff = o->off;
if((x = Bseek(o->f, off, 0)) != off){
werrstr("seek offset: need %d, got %d", off, x);
goto err;
}
o->off = off;
o->r = r;
return 0;
err:
free(r);
return -1;
}
static int
otfpoprange(Otf *o)
{
Range *r;
int x;
r = o->r;
if(r == nil){
werrstr("pop without push");
goto err;
}
if((x = Bseek(o->f, r->prevoff, 0)) != r->prevoff){
werrstr("seek offset: need %d, got %d", r->prevoff, x);
goto err;
}
o->off = r->prevoff;
o->r = r->par;
free(r);
return 0;
err:
return -1;
}
static u8int *
otfreadn(Otf *o, int n)
{
Range *r;
u8int *b;
int x;
r = o->r;
if(r != nil && o->off+n > r->start+r->len){
werrstr("need %d at %d, have %d at %d", n, o->off, r->len, r->start);
goto err;
}
if(n > o->bufsz){
if((b = realloc(o->buf, n)) == nil){
werrstr("no memory");
goto err;
}
o->buf = b;
o->bufsz = n;
}
if((x = Bread(o->f, o->buf, n)) != n){
werrstr("need %d, got %d; off %d", n, x, o->off);
goto err;
}
o->off += n;
return o->buf;
err:
return nil;
}
static int
otfarray(Otf *o, void **arr_, void *fun_, int elsz, int num)
{
int i;
int (*fun)(Otf*, void*);
u8int *arr;
if((arr = calloc(num, elsz)) == nil){
werrstr("no memory");
goto err;
}
fun = fun_;
for(i = 0; i < num; i++){
if(fun(o, arr + i*elsz) < 0)
goto err;
}
*arr_ = arr;
return 0;
err:
free(arr);
return -1;
}
int indentΔ = 2;
static int
Tfmt(Fmt *f)
{
Tm t;
s64int v = va_arg(f->args, s64int);
return fmtprint(f, "%τ", tmfmt(tmtime(&t, v, nil), nil));
}
static int
Vfmt(Fmt *f)
{
u32int v = va_arg(f->args, u32int);
return fmtprint(f, "%d.%d", v>>16, v&0xffff);
}
static int
tfmt(Fmt *f)
{
u32int v = va_arg(f->args, u32int);
return fmtprint(f, "%c%c%c%c", v>>24, v>>16, v>>8, v>>0);
}
void
otfinit(void)
{
tmfmtinstall();
fmtinstall('V', Vfmt);
fmtinstall('T', Tfmt);
fmtinstall('t', tfmt);
}