+/* ----- COMMON ROUTINES for pdf, svg and eps */
+#define min3(a, b, c) (a < b ? (a < c ? a : c) : (b < c ? b : c))
+#define max3(a, b, c) (a > b ? (a > c ? a : c) : (b > c ? b : c))
+
+#define PDF_CALC_DEBUG 0
+
+typedef struct pdf_point
+{
+ double x, y;
+} pdf_point;
+
+typedef struct
+{
+ double ascender, descender, baselineY;
+ pdf_point sizep, minp, maxp;
+ double x, y, tdx, tdy;
+ double r, cos_r, sin_r;
+ double ma, mb, mc, md, mx, my; /* pdf coord matrix */
+ double tmx, tmy; /* last 2 coords of text coord matrix */
+#if PDF_CALC_DEBUG
+ int debug;
+#endif
+} pdf_coords;
+
+#if PDF_CALC_DEBUG
+static void pdf_dump_calc(gfx_node_t *node, pdf_coords *g)
+{
+ fprintf(stderr, "PDF CALC =============================\n");
+ fprintf(stderr, " '%s' at %f pt\n", node->text, node->size);
+ fprintf(stderr, " align h = %s, v = %s, sizep = %f, %f\n",
+ (node->halign == GFX_H_RIGHT ? "r" :
+ (node->halign == GFX_H_CENTER ? "c" :
+ (node->halign == GFX_H_LEFT ? "l" : "N"))),
+ (node->valign == GFX_V_TOP ? "t" :
+ (node->valign == GFX_V_CENTER ? "c" :
+ (node->valign == GFX_V_BOTTOM ? "b" : "N"))),
+ g->sizep.x, g->sizep.y);
+ fprintf(stderr, " r = %f = %f, cos = %f, sin = %f\n",
+ g->r, node->angle, g->cos_r, g->sin_r);
+ fprintf(stderr, " ascender = %f, descender = %f, baselineY = %f\n",
+ g->ascender, g->descender, g->baselineY);
+ fprintf(stderr, " sizep: %f, %f\n", g->sizep.x, g->sizep.y);
+ fprintf(stderr, " minp: %f, %f maxp = %f, %f\n",
+ g->minp.x, g->minp.y, g->maxp.x, g->maxp.y);
+ fprintf(stderr, " x = %f, y = %f\n", g->x, g->y);
+ fprintf(stderr, " tdx = %f, tdy = %f\n", g->tdx, g->tdy);
+ fprintf(stderr, " GM = %f, %f, %f, %f, %f, %f\n",
+ g->ma, g->mb, g->mc, g->md, g->mx, g->my);
+ fprintf(stderr, " TM = %f, %f, %f, %f, %f, %f\n",
+ g->ma, g->mb, g->mc, g->md, g->tmx, g->tmy);
+}
+#endif
+
+#if PDF_CALC_DEBUG
+#define PDF_DD(x) if (g->debug) x;
+#else
+#define PDF_DD(x)
+#endif
+
+static void pdf_rotate(pdf_coords *g, pdf_point *p)
+{
+ double x2 = g->cos_r * p->x - g->sin_r * p->y;
+ double y2 = g->sin_r * p->x + g->cos_r * p->y;
+ PDF_DD( fprintf(stderr, " rotate(%f, %f) -> %f, %f\n", p->x, p->y, x2, y2))
+ p->x = x2;
+ p->y = y2;
+}
+
+
+static void pdf_calc(int page_height, gfx_node_t *node, pdf_coords *g)
+{
+ pdf_point a, b, c;
+#if PDF_CALC_DEBUG
+ /* g->debug = !!strstr(node->text, "RevProxy-1") || !!strstr(node->text, "08:00"); */
+ g->debug = !!strstr(node->text, "sekunder") || !!strstr(node->text, "Web");
+#endif
+ g->x = node->x;
+ g->y = page_height - node->y;
+ if (node->angle) {
+ g->r = 2 * M_PI * node->angle / 360.0;
+ g->cos_r = cos(g->r);
+ g->sin_r = sin(g->r);
+ } else {
+ g->r = 0;
+ g->cos_r = 1;
+ g->sin_r = 0;
+ }
+ g->ascender = afm_get_ascender(node->filename, node->size);
+ g->descender = afm_get_descender(node->filename, node->size);
+ g->sizep.x = afm_get_text_width(0, node->filename, node->size, node->tabwidth, node->text);
+ /* seems like libart ignores the descender when doing vertial-align = bottom,
+ so we do that too, to get labels v-aligning properly */
+ g->sizep.y = -g->ascender; /* + afm_get_descender(font->ps_font, node->size); */
+ g->baselineY = -g->ascender - g->sizep.y / 2;
+ a.x = g->sizep.x; a.y = g->sizep.y;
+ b.x = g->sizep.x; b.y = 0;
+ c.x = 0; c.y = g->sizep.y;
+ if (node->angle) {
+ pdf_rotate(g, &a);
+ pdf_rotate(g, &b);
+ pdf_rotate(g, &c);
+ }
+ g->minp.x = min3(a.x, b.x, c.x);
+ g->minp.y = min3(a.y, b.y, c.y);
+ g->maxp.x = max3(a.x, b.x, c.x);
+ g->maxp.y = max3(a.y, b.y, c.y);
+ /* The alignment parameters in node->valign and node->halign
+ specifies the alignment in the non-rotated coordinate system
+ (very unlike pdf/postscript), which complicates matters.
+ */
+ switch (node->halign) {
+ case GFX_H_RIGHT: g->tdx = -g->maxp.x; break;
+ case GFX_H_CENTER: g->tdx = -(g->maxp.x + g->minp.x) / 2; break;
+ case GFX_H_LEFT: g->tdx = -g->minp.x; break;
+ case GFX_H_NULL: g->tdx = 0; break;
+ }
+ switch(node->valign){
+ case GFX_V_TOP: g->tdy = -g->maxp.y; break;
+ case GFX_V_CENTER: g->tdy = -(g->maxp.y + g->minp.y) / 2; break;
+ case GFX_V_BOTTOM: g->tdy = -g->minp.y; break;
+ case GFX_V_NULL: g->tdy = 0; break;
+ }
+ g->ma = g->cos_r;
+ g->mb = g->sin_r;
+ g->mc = -g->sin_r;
+ g->md = g->cos_r;
+ g->mx = g->x + g->tdx;
+ g->my = g->y + g->tdy;
+ g->tmx = g->mx - g->ascender * g->mc;
+ g->tmy = g->my - g->ascender * g->md;
+ PDF_DD(pdf_dump_calc(node, g))
+}
+