1327 lines · 23.8 KB · C
RawDownload
#include <u.h>#include <libc.h>#include "pdf.h" enum {	Evenodd = 1<<0,	Nonstroking = 1<<1,	Leading = 1<<2,	Nextline = 1<<3,	TwTc = 1<<4,}; typedef struct Op Op; static voidmatidentity(double *arr){	double src[6] = {					1, 0,					0, 1,					0, 0	};	memcpy(arr, src, sizeof(double) * 6);} static voidmatmult(double *m1, double *m2, double *out){	double result[6];	result[0] = m1[0] * m2[0] + m1[1] * m2[2];	result[1] = m1[0] * m2[1] + m1[1] * m2[3];	result[2] = m1[2] * m2[0] + m1[3] * m2[2];	result[3] = m1[2] * m2[1] + m1[3] * m2[3];	result[4] = m1[4] * m2[0] + m1[5] * m2[2] + m2[4];	result[5] = m1[4] * m2[1] + m1[5] * m2[3] + m2[5];	memcpy(out, result, sizeof(double) * 6);} struct Op {	char *s;	int (*f)(Op *op, Page *p);	int argc;	int flags;}; static intflagless(Op *op){	if(op->flags != 0){		fprint(2, "Op '%s' expected no flags\n", op->s);		return 0;	}	return 1;} static intcobegin(Op *op, Page *p){	USED(op, p);	return 0;} static intcoend(Op *op, Page *p){	USED(op, p);	return 0;} static intgspush(Op *op, Page *p){	USED(op);	GS *r = realloc(p->GS, sizeof(GS) * (p->nGS + 1));	if(r == nil)		return 0;	p->GS = r;	p->nGS += 1;	p->GSactive = &p->GS[p->nGS - 1];	*(p->GSactive) = p->GS[p->nGS - 2];	return 1;} static intgspop(Op *op, Page *p){	USED(op);	GS *r = realloc(p->GS, sizeof(GS) * (p->nGS - 1));	if(r == nil)		return 0;	p->GS = r;	p->nGS -= 1;	p->GSactive = &p->GS[p->nGS - 1];	return 1;} /* six parameters give the inputs a,b,c,d,e,f for the matrix	[a b 0]	[c d 0]	[e f 1] That matrix should be premultiplied with the current matrix newCTM = input x oldCTM (8.3.4) */static intgsctm(Op *op, Page *p){	double input[6];	int i;	for(i = 0; i < 6; i += 1)		input[i] = arrayget(p->stack, i)->num.d;	matmult(input, p->GSactive->CTM, p->GSactive->CTM);	return flagless(op);} static intgswidth(Op *op, Page *p){	p->GSactive->LW = arrayget(p->stack, 0)->num.i;	return flagless(op);} static intgscap(Op *op, Page *p){	USED(op, p);	return 0;} static intgsjoin(Op *op, Page *p){	USED(op, p);	return 0;} static intgsmiterlim(Op *op, Page *p){	USED(op, p);	return 0;} static intgsdash(Op *op, Page *p){	USED(op, p);	return 0;} static intgsintent(Op *op, Page *p){	USED(op, p);	return 0;} static intgsflatness(Op *op, Page *p){	p->GSactive->FL = arrayget(p->stack, 0)->num.d;	return flagless(op);} static intgsstate(Op *op, Page *p){	USED(op, p);	return 0;} static intpcmove(Op *op, Page *p){	USED(op, p);	return 1;} static intpcline(Op *op, Page *p){	USED(op, p);	return 1;} static intpccurve(Op *op, Page *p){	USED(op, p);	return 1;} static intpcsubpath(Op *op, Page *p){	USED(op, p);	return 0;} static intpcrect(Op *op, Page *p){	USED(op, p);	return 0;} static intppstroke(Op *op, Page *p){	USED(op, p);	return 1;} static intppstrokec(Op *op, Page *p){	USED(op, p);	return 0;} static intppfill(Op *op, Page *p){	USED(op, p);	return 0;} static intppfills(Op *op, Page *p){	USED(op, p);	return 0;} static intppfillcfs(Op *op, Page *p){	USED(op, p);	return 0;} static intppc(Op *op, Page *p){	USED(op, p);	return 0;} static intcpclip(Op *op, Page *p){	USED(op, p);	return 0;} static intcspace(Op *op, Page *p){	USED(op, p);	return 0;} static intccolour(Op *op, Page *p){	USED(op, p);	return 0;} static intccolour2(Op *op, Page *p){	USED(op, p);	return 0;} static intcgray(Op *op, Page *p){	int value = 255 * arrayget(p->stack, 0)->num.d;	int i;	u32int *color;	if(op->flags & Nonstroking){		color = &p->GSactive->NSC;		p->GSactive->NSCS = DeviceGray;	} else{		color = &p->GSactive->SC;		p->GSactive->SCS = DeviceGray;	}	*color = 0;	for(i = 0; i < 3; i += 1)		*color = (*color | value) << 8;	*color |= 255;	return 1;} static intcrgb(Op *op, Page *p){	USED(op, p);	return 0;} static intccmyk(Op *op, Page *p){	USED(op, p);	return 0;} static intsshade(Op *op, Page *p){	USED(op, p);	return 0;} static inteoobject(Op *op, Page *p){	USED(op, p);	return 0;} static intiibegin(Op *op, Page *p){	USED(op, p);	return 0;} static intiidata(Op *op, Page *p){	USED(op, p);	return 0;} static intiiend(Op *op, Page *p){	USED(op, p);	return 0;} static inttsspace(Op *op, Page *p){	USED(op, p);	return 0;} static inttswspace(Op *op, Page *p){	USED(op, p);	return 0;} static inttshscale(Op *op, Page *p){	USED(op, p);	return 0;} static inttslead(Op *op, Page *p){	p->TS.TL = arrayget(p->stack, 0)->num.d;	return flagless(op);} static intfontwidths(Page *p){	Object *o;	int i;	if(p->GSactive->Font.widths != nil)		free(p->GSactive->Font.widths);	o = dictget(p->GSactive->Font.font, "FirstChar");	if(o == nil)		return 1;	p->GSactive->Font.first = o->num.i;	p->GSactive->Font.last = dictget(p->GSactive->Font.font, "LastChar")->num.i;	p->GSactive->Font.widths = malloc(sizeof(int) * (p->GSactive->Font.last - p->GSactive->Font.first + 1));	if(p->GSactive->Font.widths == nil){		print("Failed to allocate for (%d, %d): %d\n", p->GSactive->Font.first, p->GSactive->Font.last, p->GSactive->Font.last - p->GSactive->Font.first + 1);		return 1;	}	o = dictget(p->GSactive->Font.font, "Widths");	if(o == nil)		return 0;	for(i = 0; i < arraylen(o); i += 1)		p->GSactive->Font.widths[i] = arrayget(o, i)->num.i;	o = dictget(p->GSactive->Font.font, "FontDescriptor");	p->GSactive->Font.defwidth = dictget(o, "MissingWidth")->num.i;	return 1;} static inttsfontsz(Op *op, Page *p){	char *name = arrayget(p->stack, 0)->name;	p->GSactive->Font.font = dictget(dictget(dictget(p->obj, "Resources"), "Font"), name);	if(p->GSactive->Font.font == nil){		werrstr("Font not found: '%s'", name);		return 0;	}	p->GSactive->Font.enc = dictget(p->GSactive->Font.font, "Encoding");	if(p->GSactive->Font.enc)		p->GSactive->Font.enc = dictget(p->GSactive->Font.enc, "Differences");	p->GSactive->Font.size = arrayget(p->stack, 1)->num.d;	return fontwidths(p) && flagless(op);} static inttsrendmode(Op *op, Page *p){	USED(op, p);	return 0;} static inttsrise(Op *op, Page *p){	USED(op, p);	return 0;} static inttobegin(Op *op, Page *p){	if(p->TS.inobj){		werrstr("Text objects must not be nested");		return 0;	}	matidentity(p->TS.Tm);	matidentity(p->TS.Tlm);	p->TS.inobj = 1;	p->GSactive->Font.font = nil;	return flagless(op);} static inttoend(Op *op, Page *p){	if(!p->TS.inobj){		werrstr("ET found without BT");		return 0;	}	p->TS.inobj = 0;	return flagless(op);} static inttmove(Page *p, double x, double y, int tlm){	double shift[6] = {1, 0, 0, 1, x, y};	if(tlm){		matmult(shift, p->TS.Tlm, p->TS.Tlm);		memcpy(p->TS.Tm, p->TS.Tlm, sizeof(double) * 6);	} else{		matmult(shift, p->TS.Tm, p->TS.Tm);	}	return 1;} static inttpmove(Op *op, Page *p){	Object *x, *y;	x = arrayget(p->stack, 0);	y = arrayget(p->stack, 1);	if(op->flags & Leading)		p->TS.TL = -y->num.d;	return tmove(p, x->num.d, y->num.d, 1);} static inttpmatrix(Op *op, Page *p){	int i;	for(i = 0; i < 6; i += 1){		p->TS.Tm[i] = arrayget(p->stack, i)->num.d;		p->TS.Tlm[i] = p->TS.Tm[i];	}	return flagless(op);} static inttpmove0(Op *op, Page *p){	return tmove(p, 0, 0 - p->TS.TL, 1) && flagless(op);} //TODO: replace this with a precomputed map when the font is loadedstatic intwritepatched(Page *p, uchar c){

Lines 1–500 of 1327.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t