shithub: pdffs

Download patch

ref: b1ad1cffd79e7552f06df0381ce58a7571da3dea
parent: 61b5e458d92d9341a71fb038c4ffe529e69764a8
author: Noam Preil <noam@pixelhero.dev>
date: Fri Apr 8 09:50:51 EDT 2022

op: simplify matrix math

--- a/op.c
+++ b/op.c
@@ -38,6 +38,28 @@
 	memcpy(out, result, sizeof(double) * 6);
 }
 
+static void
+mattrans(double *m1, double x, double y, double *out)
+{
+	double mult[6] = {
+		1, 0,
+		0, 1,
+		x, y,
+	};
+	matmult(mult, m1, out);
+}
+
+static void
+matscale(double *m1, double x, double y, double *out)
+{
+	double mult[6] = {
+		x, 0,
+		0, y,
+		0, 0,
+	};
+	matmult(mult, m1, out);
+}
+
 struct Op {
 	char *s;
 	int (*f)(Op *op, Page *p);
@@ -473,17 +495,13 @@
 	return flagless(op);
 }
 
-static int
+static void
 tmove(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);
+	double *mat = tlm ? p->TS.Tlm : p->TS.Tm;
+	mattrans(mat, x, y, mat);
+	if(tlm)
 		memcpy(p->TS.Tm, p->TS.Tlm, sizeof(double) * 6);
-	} else{
-		matmult(shift, p->TS.Tm, p->TS.Tm);
-	}
-	return 1;
 }
 
 static int
@@ -494,7 +512,8 @@
 	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);
+	tmove(p, x->num.d, y->num.d, 1);
+	return 1;
 }
 
 static int
@@ -511,7 +530,8 @@
 static int
 tpmove0(Op *op, Page *p)
 {
-	return tmove(p, 0, 0 - p->TS.TL, 1) && flagless(op);
+	tmove(p, 0, 0 - p->TS.TL, 1);
+	return flagless(op);
 }
 
 //TODO: replace this with a precomputed map when the font is loaded
@@ -612,22 +632,36 @@
 	return bufput(&p->buf, (uchar*)&c, 1) == 1;
 }
 
+static double
+glyphwidth(Page *p, ulong c)
+{
+	if(c >= p->GSactive->Font.first && c <= p->GSactive->Font.last)
+		return (double)p->GSactive->Font.widths[c - p->GSactive->Font.first] / 1000;
+	return (double)p->GSactive->Font.defwidth / 1000;
+}
+
+static double
+glyphspacing(Page *p, ulong c)
+{
+	double Tfs = p->GSactive->Font.size;
+	double w0 = glyphwidth(p, c);
+	double tx = w0 * Tfs + p->TS.Tc;
+	if(c == ' ')
+		tx += p->TS.Tw;
+	return tx;
+}
+
 /* Renders one character / glyph and updates the text state */
 static int
 tchar(Page *p, ulong c)
 {
-	double Trm[6] = {p->GSactive->Font.size, 0, 0, p->GSactive->Font.size, 0, 0};
-	double tx, w0;
+	double Tfs = p->GSactive->Font.size;
+	double Trm[6];
+	double tx;
 	int i;
-	matmult(Trm, p->TS.Tm, Trm);
+	/* Text rendering matrix converts coordinates from font space to device space */
+	matscale(p->TS.Tm, Tfs, Tfs, Trm);
 	matmult(Trm, p->GSactive->CTM, Trm);
-	if(c >= p->GSactive->Font.first && c <= p->GSactive->Font.last)
-		w0 = (double)p->GSactive->Font.widths[c - p->GSactive->Font.first] / 1000;
-	else
-		w0 = (double)p->GSactive->Font.defwidth / 1000;
-	tx = w0 * p->GSactive->Font.size + p->TS.Tc;
-	if(c == ' ')
-		tx += p->TS.Tw;
 	// Check if whitespace is needed
 	if(p->buf.sz > 1){
 		if(p->TS.y != Trm[5]){
@@ -647,7 +681,8 @@
 	}
 	if(p->buf.b != nil)
 		memimagestring(p->image, Pt(Trm[4], 1100 - Trm[5]), memblack, Pt(0,0), getmemdefont(), (char*)p->buf.b + oend);
-	tmove(p, tx, 0, 0);
+	tx = glyphspacing(p, c);
+	mattrans(p->TS.Tm, tx, 0, p->TS.Tm);
 	p->TS.x = Trm[4] + tx;
 	p->TS.y = Trm[5];
 	return 1;
@@ -683,14 +718,11 @@
 	int i;
 	for(i = 0; i < arraylen(arr); i += 1){
 		o = arrayget(arr, i);
-		if(o->type == Ostr){
+		if(o->type == Ostr)
 			if(!tstr(p, o->str, o->len))
 				return 0;
-		}
-		else{
-			if(!tmove(p, 0 - (o->num.d / 1000), 0, 0))
-				return 0;
-		}
+		else
+			mattrans(p->TS.Tm, 0 - (o->num.d / 1000), 0, p->TS.Tm);
 	}
 	return flagless(op);
 }
@@ -1322,7 +1354,7 @@
 			werrstr("unimplemented or error not reported properly");
 			if(!op->f(op, p)){
 				werrstr("renderer: %s failed: %r", op->s);
-				return 0;
+			//	return 0;
 			}
 			if(!stackreset(p))
 				return 0;