ref: c8e83c81d910049123621d766bc837abc9103145
dir: /otf.c.in/
/* this file is generated. do not modify. */
#include <u.h>
#include <libc.h>
#include <bio.h>
#include "otf.h"
typedef struct Range Range;
struct Otf {
Biobuf *f;
Range *r;
u8int *buf;
int bufsz;
int off;
/* extra fields to simplify parsing */
OTF_EXTRA_FIELDS
};
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;
}
static int
read_ComponentGlyph(Otf *o, ComponentGlyph **out, int instr)
{
ComponentGlyph *v;
u8int *b;
if((v = calloc(1, sizeof(*v))) == nil){
nomem:
werrstr("no memory");
goto err;
}
if((b = otfreadn(o, 2*2)) == nil)
goto err;
v->flags = b[0]<<8 | b[1];
v->glyphIndex = b[2]<<8 | b[3];
instr |= v->flags & CGLYPH_FL_INSTRUCTIONS;
if((v->flags & CGLYPH_FL_WORD_ARGS) != 0 && (b = otfreadn(o, 2*2)) != nil){
v->arg1.u16 = b[0]<<8 | b[1];
v->arg2.u16 = b[2]<<8 | b[3];
}else if((b = otfreadn(o, 2)) != nil){
v->arg1.u8 = b[0];
v->arg2.u8 = b[1];
}
if(b == nil)
goto err;
if((v->flags & CGLYPH_FL_SCALE) != 0 && (b = otfreadn(o, 2)) != nil){
v->scale = (b[0]<<8 | b[1]>>14)+(b[0]<<8 | b[1]&((1<<14)-1))/16384.0;
}else if((v->flags & CGLYPH_FL_SCALE_XY) != 0 && (b = otfreadn(o, 2*2)) != nil){
v->scaleX = (b[0]<<8 | b[1]>>14)+(b[0]<<8 | b[1]&((1<<14)-1))/16384.0;
v->scaleY = (b[2]<<8 | b[3]>>14)+(b[2]<<8 | b[3]&((1<<14)-1))/16384.0;
}else if((v->flags & CGLYPH_FL_2X2_TRANSFORM) != 0 && (b = otfreadn(o, 2*2*2)) != nil){
v->scaleX = (b[0]<<8 | b[1]>>14)+(b[0]<<8 | b[1]&((1<<14)-1))/16384.0;
v->scale01 = (b[2]<<8 | b[3]>>14)+(b[2]<<8 | b[3]&((1<<14)-1))/16384.0;
v->scale10 = (b[4]<<8 | b[5]>>14)+(b[4]<<8 | b[5]&((1<<14)-1))/16384.0;
v->scaleY = (b[6]<<8 | b[7]>>14)+(b[6]<<8 | b[7]&((1<<14)-1))/16384.0;
}
if(b == nil)
goto err;
if((v->flags & CGLYPH_FL_MORE_COMPONENTS) != 0){
if(read_ComponentGlyph(o, &v->next, instr) != 0){
free(v);
return -1;
}
}else if(instr != 0){
if((b = otfreadn(o, 2)) == nil)
goto err;
v->numInstr = b[0]<<8 | b[1];
if((v->instr = malloc(v->numInstr)) == nil)
goto nomem;
if(v->numInstr > 0 && (b = otfreadn(o, v->numInstr)) == nil)
goto err;
memcpy(v->instr, b, v->numInstr);
}
*out = v;
return 0;
err:
if(v != nil)
free(v->instr);
free(v);
werrstr("ComponentGlyph: %r");
return -1;
}
enum {
GLYPH_FL_ON_CURVE_POINT = 1<<0,
GLYPH_FL_X_SHORT_VECTOR = 1<<1,
GLYPH_FL_Y_SHORT_VECTOR = 1<<2,
GLYPH_FL_REPEAT = 1<<3,
GLYPH_FL_X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR = 1<<4,
GLYPH_FL_Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR = 1<<5,
GLYPH_FL_OVERLAP_SIMPLE = 1<<6,
};
static int
read_SimpleGlyph(Otf *o, SimpleGlyph **out)
{
SimpleGlyph *v;
u8int *b, *flags;
int i, n, nflags, c;
flags = nil;
if((v = calloc(1, sizeof(*v))) == nil){
nomem:
werrstr("no memory");
goto err;
}
n = o->numberOfContours;
if((b = otfreadn(o, 2*n+2)) == nil)
goto err;
if((v->endPtsOfContours = malloc(2*n)) == nil)
goto nomem;
for(int i = 0; i < n; i++)
v->endPtsOfContours[i] = b[2*i+0]<<8 | b[2*i+1];
v->instructionLength = b[2*n+0]<<8 | b[2*n+1];
n = v->instructionLength;
if((b = otfreadn(o, n)) == nil)
goto err;
if((v->instructions = malloc(n)) == nil)
goto nomem;
memcpy(v->instructions, b, n);
if((flags = malloc(v->numPoints)) == nil) /* not supposed to be more than that, 64Kb max */
goto nomem;
for(nflags = 0; nflags < v->numPoints;){
if((b = otfreadn(o, 1)) == nil)
goto err;
flags[nflags] = *b;
if((flags[nflags] & GLYPH_FL_REPEAT) != 0){
flags[nflags] ^= GLYPH_FL_REPEAT;
if((b = otfreadn(o, 1)) == nil)
goto err;
if(nflags + 1 + *b > v->numPoints){
werrstr("repeat overflow");
goto err;
}
memset(flags+nflags+1, flags[nflags], *b);
nflags += 1 + *b;
}else{
nflags++;
}
}
v->numPoints = v->endPtsOfContours[o->numberOfContours-1];
if((v->points = calloc(v->numPoints, sizeof(*v->points))) == nil)
goto nomem;
/* flags first */
for(i = n = 0; i < nflags && n < v->numPoints; i++, n++)
v->points[n].onCurve = (flags[i] & GLYPH_FL_ON_CURVE_POINT) != 0;
/* read packed x coordinates */
c = 0;
for(i = n = 0; i < nflags && n < v->numPoints; i++){
if((flags[i] & GLYPH_FL_X_SHORT_VECTOR) != 0){
if((b = otfreadn(o, 1)) == nil)
goto err;
c = *b;
if((flags[i] & GLYPH_FL_X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR) == 0)
c = -c;
v->points[n++].x = c;
}else if((flags[i] & GLYPH_FL_X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR) != 0){
v->points[n++].x = c;
}else{
if((b = otfreadn(o, 2)) == nil)
goto err;
c += (s16int)(b[0]<<8 | b[1]);
v->points[n++].x = c;
}
}
/* read packed y coordinates */
c = 0;
for(i = n = 0; i < nflags && n < v->numPoints; i++){
if((flags[i] & GLYPH_FL_Y_SHORT_VECTOR) != 0){
if((b = otfreadn(o, 1)) == nil)
goto err;
c = *b;
if((flags[i] & GLYPH_FL_Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR) == 0)
c = -c;
v->points[n++].y = c;
}else if((flags[i] & GLYPH_FL_Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR) != 0){
v->points[n++].y = c;
}else{
if((b = otfreadn(o, 2)) == nil)
goto err;
c += (s16int)(b[0]<<8 | b[1]);
v->points[n++].y = c;
}
}
free(flags);
*out = v;
return 0;
err:
free(flags);
if(v != nil){
free(v->endPtsOfContours);
free(v->instructions);
free(v->points);
}
free(v);
werrstr("SimpleGlyph: %r");
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);
if(v == 0)
return fmtprint(f, "<nil>");
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);
}