+
+void gfxmatrix_transform(gfxmatrix_t*m, double* v, double*dest)
+{
+ dest[0] = m->m00*v[0] + m->m10*v[1] + m->tx;
+ dest[1] = m->m01*v[0] + m->m11*v[1] + m->ty;
+}
+void gfxmatrix_invert(gfxmatrix_t*m, gfxmatrix_t*dest)
+{
+ double det = m->m00 * m->m11 - m->m10 * m->m01;
+ if(!det) {
+ memset(dest, 0, sizeof(gfxmatrix_t));
+ return;
+ }
+ det = 1/det;
+ dest->m00 = m->m11 * det;
+ dest->m01 = -m->m01 * det;
+ dest->m10 = -m->m10 * det;
+ dest->m11 = m->m00 * det;
+ dest->tx = -(dest->m00 * m->tx + dest->m10 * m->ty);
+ dest->ty = -(dest->m01 * m->tx + dest->m11 * m->ty);
+}
+void gfxmatrix_unit(gfxmatrix_t*m)
+{
+ memset(m, 0, sizeof(gfxmatrix_t));
+ m->m00 = 1.0;
+ m->m11 = 1.0;
+}
+void gfxmatrix_multiply(gfxmatrix_t*m1, gfxmatrix_t*m2, gfxmatrix_t*dest)
+{
+ dest->m00 = m1->m00*m2->m00 + m1->m10*m2->m01 + m1->tx;
+ dest->m01 = m1->m01*m2->m00 + m1->m11*m2->m01 + m1->ty;
+ dest->m10 = m1->m00*m2->m10 + m1->m10*m2->m11 + m1->tx;
+ dest->m11 = m1->m01*m2->m10 + m1->m11*m2->m11 + m1->ty;
+ dest->tx = m1->m00*m2->tx + m1->m10*m2->ty + m1->tx;
+ dest->ty = m1->m01*m2->tx + m1->m11*m2->ty + m1->ty;
+}
+
+gfxfontlist_t* gfxfontlist_create()
+{
+ /* Initial list ist empty */
+ return 0;
+}
+
+gfxfont_t*gfxfontlist_findfont(gfxfontlist_t*list, char*id)
+{
+ gfxfontlist_t*l = list;
+ while(l) {
+ if(!strcmp((char*)l->font->id, id)) {
+ return l->font;
+ }
+ l = l->next;
+ }
+ return 0;
+}
+char gfxfontlist_hasfont(gfxfontlist_t*list, gfxfont_t*font)
+{
+ gfxfontlist_t*l = list;
+ while(l) {
+ if(!strcmp((char*)l->font->id, font->id)) {
+ return 1;
+ }
+ l = l->next;
+ }
+ return 0;
+}
+gfxfontlist_t*gfxfontlist_addfont(gfxfontlist_t*list, gfxfont_t*font)
+{
+ gfxfontlist_t*last=0,*l = list;
+ while(l) {
+ last = l;
+ if(!strcmp((char*)l->font->id, font->id)) {
+ return list; // we already know this font
+ }
+ l = l->next;
+ }
+ if(!font) {
+ fprintf(stderr, "Tried to add zero font\n");
+ }
+ l = (gfxfontlist_t*)rfx_calloc(sizeof(gfxfontlist_t));
+ l->font = font;
+ l->next = 0;
+ if(last) {
+ last->next = l;
+ return list;
+ } else {
+ return l;
+ }
+}
+
+gfxline_t*gfxline_makerectangle(int x1,int y1,int x2, int y2)
+{
+ gfxline_t* line = (gfxline_t*)rfx_calloc(sizeof(gfxline_t)*5);
+ line[0].x = x1;line[0].y = y1;line[0].type = gfx_moveTo;line[0].next = &line[1];
+ line[1].x = x2;line[1].y = y1;line[1].type = gfx_lineTo;line[1].next = &line[2];
+ line[2].x = x2;line[2].y = y2;line[2].type = gfx_lineTo;line[2].next = &line[3];
+ line[3].x = x1;line[3].y = y2;line[3].type = gfx_lineTo;line[3].next = &line[4];
+ line[4].x = x1;line[4].y = y1;line[4].type = gfx_lineTo;
+ return line;
+}