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;