]> granicus.if.org Git - graphviz/commitdiff
cleaning up pagination code
authorellson <devnull@localhost>
Thu, 27 Jan 2005 06:27:30 +0000 (06:27 +0000)
committerellson <devnull@localhost>
Thu, 27 Jan 2005 06:27:30 +0000 (06:27 +0000)
12 files changed:
lib/common/emit.c
lib/common/macros.h
lib/common/output.c
lib/common/renderprocs.h
lib/common/types.h
lib/common/utils.c
lib/fdpgen/fdp.h
lib/gvc/gvc.h
lib/gvc/gvcint.h
lib/gvc/gvplugin_render.h
lib/gvc/gvrender.c
lib/neatogen/constraint.c

index 7f84645287173c4117c08f6e8a7e2d0f82389d2e..f31bd1bd0f61b352ee8581dc88fead605185b1b3 100644 (file)
 
 #define MAX_CODEGENS 100
 
+#define PAGINATIONBUG 1
+
 char *BaseLineStyle[3] = { "solid\0", "setlinewidth\0001\0", 0 };
 int Obj;
-static int Page;               /* w.r.t. unrotated coords */
-static int Layer, Nlayers;
-static char **LayerID;
-static box PB;                 /* drawable region in device coords */
-static pointf GP;              /* graph page size, in graph coords */
-static box CB;                 /* current page box, in graph coords */
-static point PFC;              /* device page box for centering */
 static double Deffontsize;
 static char *Deffontname;
-static char *Layerdelims;
 static attrsym_t *G_peripheries;
 
 static point exch_xy(point p)
@@ -65,70 +59,81 @@ static pointf exch_xyf(pointf p)
 
 /* parse_layers:
  * Split input string into tokens, with separators specified by
- * the layersep attribute. Store the values in the LayerID array,
+ * the layersep attribute. Store the values in the gvc->layerIDs array,
  * starting at index 1, and return the count.
  * Free previously stored list. Note that there is no mechanism
  * to free the memory before exit.
  */
-static int parse_layers(graph_t * g, char *p)
+static int parse_layers(GVC_t *gvc, graph_t * g, char *p)
 {
     int ntok;
-    char *pcopy;
     char *tok;
     int sz;
 
-    Layerdelims = agget(g, "layersep");
-    if (!Layerdelims)
-       Layerdelims = DEFAULT_LAYERSEP;
+    gvc->layerDelims = agget(g, "layersep");
+    if (!gvc->layerDelims)
+       gvc->layerDelims = DEFAULT_LAYERSEP;
 
     ntok = 0;
     sz = 0;
-    pcopy = strdup(p);
+    gvc->layers = strdup(p);
 
-    if (LayerID)
-       free(LayerID);
-    LayerID = 0;
-    for (tok = strtok(pcopy, Layerdelims); tok;
-        tok = strtok(NULL, Layerdelims)) {
+    for (tok = strtok(gvc->layers, gvc->layerDelims); tok;
+        tok = strtok(NULL, gvc->layerDelims)) {
        ntok++;
        if (ntok > sz) {
            sz += SMALLBUF;
-           LayerID = ALLOC(sz, LayerID, char *);
+           gvc->layerIDs = ALLOC(sz, gvc->layerIDs, char *);
        }
-       LayerID[ntok] = tok;
+       gvc->layerIDs[ntok] = tok;
     }
     if (ntok) {
-       LayerID = RALLOC(ntok + 2, LayerID, char *);    /* shrink to minimum size */
-       LayerID[0] = NULL;
-       LayerID[ntok + 1] = NULL;
+       gvc->layerIDs = RALLOC(ntok + 2, gvc->layerIDs, char *);        /* shrink to minimum size */
+       gvc->layerIDs[0] = NULL;
+       gvc->layerIDs[ntok + 1] = NULL;
     }
 
     return ntok;
 }
 
-static void setup_layering(GVC_t * gvc, graph_t * g)
+static void init_layering(GVC_t * gvc, graph_t * g)
 {
     char *str;
 
+    /* free layer strings and pointers from previous graph */
+    if (gvc->layers)
+       free(gvc->layers);
+    if (gvc->layerIDs)
+       free(gvc->layerIDs);
+
     if ((str = agget(g, "layers")) != 0) {
        if (gvrender_features(gvc) & GVRENDER_DOES_LAYERS) {
-           Nlayers = parse_layers(g, str);
+           gvc->numLayers = parse_layers(gvc, g, str);
        }
        else {
            agerr(AGWARN, "layers not supported in %s output\n",
                  gvc->job->output_langname);
-           Nlayers = 0;
+           gvc->numLayers = 1;
        }
     } else {
-       LayerID = NULL;
-       Nlayers = 0;
+       gvc->layerIDs = NULL;
+       gvc->numLayers = 1;
     }
 }
 
-static void reset_layering(GVC_t * gvc, graph_t * g)
+static void firstlayer(GVC_t *gvc)
+{
+    gvc->layerNum = 1;
+}
+
+static boolean validlayer(GVC_t *gvc)
+{
+    return (gvc->layerNum <= gvc->numLayers);
+}
+
+static void nextlayer(GVC_t *gvc)
 {
-    Layer = Nlayers = 0;
-    LayerID = NULL;   /* FIXME - poss leak of array of layer names? */
+    gvc->layerNum++;
 }
 
 static point pagecode(GVC_t *gvc, char c)
@@ -160,6 +165,7 @@ static void set_pagedir(GVC_t *gvc, graph_t * g)
 
     gvc->pagesArrayMajor.x = gvc->pagesArrayMajor.y 
                = gvc->pagesArrayMinor.x = gvc->pagesArrayMinor.y = 0;
+    gvc->pagesArrayFirst.x = gvc->pagesArrayFirst.y = 0;
     str = agget(g, "pagedir");
     if (str && str[0]) {
        gvc->pagesArrayMajor = pagecode(gvc, str[0]);
@@ -167,44 +173,44 @@ static void set_pagedir(GVC_t *gvc, graph_t * g)
     }
     if ((abs(gvc->pagesArrayMajor.x + gvc->pagesArrayMinor.x) != 1)
      || (abs(gvc->pagesArrayMajor.y + gvc->pagesArrayMinor.y) != 1)) {
-       gvc->pagesArrayMajor.x = 0;
-       gvc->pagesArrayMajor.y = 1;
-       gvc->pagesArrayMinor.x = 1;
-       gvc->pagesArrayMinor.y = 0;
-       gvc->pagesArrayFirst.x = gvc->pagesArrayFirst.y = 0;
+       gvc->pagesArrayMajor = pagecode(gvc, 'B');
+       gvc->pagesArrayMinor = pagecode(gvc, 'L');
        if (str)
            agerr(AGWARN, "pagedir=%s ignored\n", str);
     }
 }
 
-static void setup_pagination(GVC_t * gvc, graph_t * g)
+static void init_job_pagination(GVC_t * gvc, graph_t * g)
 {
-    point PFCLM;               /* page for centering less margins */
-    point DS;                  /* device drawable region for a page of the graph */
+    gvrender_job_t *job = gvc->job;
+    pointf PFCLM;              /* page for centering less margins */
+    pointf DS;                 /* device drawable region for a page of the graph */
 
     /* determine pagination */
-    PB.LL = GD_drawing(g)->margin;
-    if ((GD_drawing(g)->page.x > 0) && (GD_drawing(g)->page.y > 0)) {
+    job->pageBox.LL = job->margin;
+    if (gvc->graph_sets_page) {
        /* page was set by user */
        point tp;
-       PFC = GD_drawing(g)->page;
-       PFCLM.x = PFC.x - 2 * PB.LL.x;
-       PFCLM.y = PFC.y - 2 * PB.LL.y;
-       GP.x = PFCLM.x;
-       GP.y = PFCLM.y;         /* convert to double */
+       job->pageBoxCentered = gvc->page;
+       PFCLM.x = job->pageBoxCentered.x - 2 * job->pageBox.LL.x;
+       PFCLM.y = job->pageBoxCentered.y - 2 * job->pageBox.LL.y;
+       gvc->pageSize.x = PFCLM.x;
+       gvc->pageSize.y = PFCLM.y;              /* convert to double */
        if (GD_drawing(g)->landscape)
-           GP = exch_xyf(GP);
-       GP.x = GP.x / gvc->job->zoom;
-       GP.y = GP.y / gvc->job->zoom;
+           gvc->pageSize = exch_xyf(gvc->pageSize);
+       gvc->pageSize.x /= gvc->job->zoom;
+       gvc->pageSize.y /= gvc->job->zoom;
        /* we don't want graph page to exceed its bounding box */
-       GP.x = MIN(GP.x, GD_bb(g).UR.x);
-       GP.y = MIN(GP.y, GD_bb(g).UR.y);
-       gvc->pagesArraySize.x = (GP.x > 0) ? ceil(((double) GD_bb(g).UR.x) / GP.x) : 1;
-       gvc->pagesArraySize.y = (GP.y > 0) ? ceil(((double) GD_bb(g).UR.y) / GP.y) : 1;
-       gvc->pagesSize = gvc->pagesArraySize.x * gvc->pagesArraySize.y;
+       gvc->pageSize.x = MIN(gvc->pageSize.x, gvc->bb.UR.x);
+       gvc->pageSize.y = MIN(gvc->pageSize.y, gvc->bb.UR.y);
+       gvc->pagesArraySize.x =
+           (gvc->pageSize.x > 0) ? ceil((gvc->bb.UR.x) / gvc->pageSize.x) : 1;
+       gvc->pagesArraySize.y =
+           (gvc->pageSize.y > 0) ? ceil((gvc->bb.UR.y) / gvc->pageSize.y) : 1;
+       gvc->numPages = gvc->pagesArraySize.x * gvc->pagesArraySize.y;
 
        /* find the drawable size in device coords */
-#if 1
+#ifdef PAGINATIONBUG
        tp = GD_drawing(g)->size;
 #else
        tp.x = gvc->job->width;
@@ -217,21 +223,21 @@ static void setup_pagination(GVC_t * gvc, graph_t * g)
     } else {
        /* page not set by user, assume default when centering,
           but allow infinite page for any other interpretation */
-       GP.x = GD_bb(g).UR.x;
-       GP.y = GD_bb(g).UR.y;
-       PFC.x = DEFAULT_PAGEWD;
-       PFC.y = DEFAULT_PAGEHT;
-       PFCLM.x = PFC.x - 2 * PB.LL.x;
-       PFCLM.y = PFC.y - 2 * PB.LL.y;
-#if 1
-       DS = GD_drawing(g)->size;
+       gvc->pageSize.x = gvc->bb.UR.x;
+       gvc->pageSize.y = gvc->bb.UR.y;
+       job->pageBoxCentered.x = DEFAULT_PAGEWD;
+       job->pageBoxCentered.y = DEFAULT_PAGEHT;
+       PFCLM.x = job->pageBoxCentered.x - 2 * job->pageBox.LL.x;
+       PFCLM.y = job->pageBoxCentered.y - 2 * job->pageBox.LL.y;
+#ifdef PAGINATIONBUG
+       P2PF(GD_drawing(g)->size, DS);
 #else
        DS.x = gvc->job->width;
        DS.y = gvc->job->height;
 #endif
        if (GD_drawing(g)->landscape)
-           DS = exch_xy(DS);
-       gvc->pagesArraySize.x = gvc->pagesArraySize.y = gvc->pagesSize = 1;
+           DS = exch_xyf(DS);
+       gvc->pagesArraySize.x = gvc->pagesArraySize.y = gvc->numPages = 1;
     }
 
     set_pagedir(gvc, g);
@@ -243,23 +249,37 @@ static void setup_pagination(GVC_t * gvc, graph_t * g)
            extra.x = 0;
        if ((extra.y = PFCLM.y - DS.y) < 0)
            extra.y = 0;
-       PB.LL.x += extra.x / 2;
-       PB.LL.y += extra.y / 2;
+       job->pageBox.LL.x += extra.x / 2;
+       job->pageBox.LL.y += extra.y / 2;
     }
-    PB.UR = add_points(PB.LL, DS);
+    job->pageBox.UR = add_pointfs(job->pageBox.LL, DS);
 }
 
-static void reset_pagination(GVC_t * gvc, graph_t * g)
+static void firstpage(GVC_t *gvc)
 {
-    Page = 0;
-    gvc->pagesArrayFirst.x = gvc->pagesArrayFirst.y = 0;
-    gvc->pagesArrayMajor.x = gvc->pagesArrayMajor.y = 0;
-    gvc->pagesArrayMinor.x = gvc->pagesArrayMinor.y = 0;
-    gvc->pagesArraySize.x = gvc->pagesArraySize.y = gvc->pagesSize = 1;
-    PB.LL.x = PB.LL.y = PB.UR.x = PB.UR.y = 0;
-    GP.x = GP.y = 0;
-    CB.LL.x = CB.LL.y = CB.UR.x = CB.UR.y = 0;
-    PFC.x = PFC.y = 0;
+    gvc->pagesArrayElem = gvc->pagesArrayFirst;
+    gvc->pageNum = 1;
+}
+
+static int validpage(GVC_t *gvc)
+{
+    return ((gvc->pagesArrayElem.x >= 0)
+        && (gvc->pagesArrayElem.x < gvc->pagesArraySize.x)
+        && (gvc->pagesArrayElem.y >= 0)
+        && (gvc->pagesArrayElem.y < gvc->pagesArraySize.y));
+}
+
+static void nextpage(GVC_t *gvc)
+{
+    gvc->pagesArrayElem = add_points(gvc->pagesArrayElem, gvc->pagesArrayMinor);
+    if (validpage(gvc) == FALSE) {
+       if (gvc->pagesArrayMajor.y)
+           gvc->pagesArrayElem.x = gvc->pagesArrayFirst.x;
+       else
+           gvc->pagesArrayElem.y = gvc->pagesArrayFirst.y;
+       gvc->pagesArrayElem = add_points(gvc->pagesArrayElem, gvc->pagesArrayMajor);
+    }
+    gvc->pageNum = gvc->pagesArrayElem.x + gvc->pagesArrayElem.y * gvc->pagesArraySize.x + 1;
 }
 
 static int write_edge_test(Agraph_t * g, Agedge_t * e)
@@ -292,10 +312,6 @@ void emit_reset(GVC_t * gvc, graph_t * g)
 {
     Agnode_t *n;
 
-    reset_layering(gvc, g);
-
-    reset_pagination(gvc, g);
-
     /* reset state */
     for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
        ND_state(n) = 0;
@@ -305,20 +321,22 @@ void emit_reset(GVC_t * gvc, graph_t * g)
     gvrender_reset(gvc);
 }
 
-static void emit_background(GVC_t * gvc, point LL, point UR)
+static void emit_background(GVC_t * gvc, boxf pageBox)
 {
     char *str;
     point A[4];
     graph_t *g = gvc->g;
+    box PB;
 
     if (((str = agget(g, "bgcolor")) != 0)
        && str[0]
        && strcmp(str, "white") != 0 && strcmp(str, "transparent") != 0) {
        /* increment to cover int rounding errors */
-       A[0].x = A[1].x = LL.x - GD_drawing(g)->margin.x - 1;
-       A[2].x = A[3].x = UR.x + GD_drawing(g)->margin.x + 1;
-       A[1].y = A[2].y = UR.y + GD_drawing(g)->margin.y + 1;
-       A[3].y = A[0].y = LL.y - GD_drawing(g)->margin.y - 1;
+       BF2B(pageBox, PB);
+       A[0].x = A[1].x = PB.LL.x - GD_drawing(g)->margin.x - 1;
+       A[2].x = A[3].x = PB.UR.x + GD_drawing(g)->margin.x + 1;
+       A[1].y = A[2].y = PB.UR.y + GD_drawing(g)->margin.y + 1;
+       A[3].y = A[0].y = PB.LL.y - GD_drawing(g)->margin.y - 1;
        gvrender_set_fillcolor(gvc, str);
        gvrender_set_pencolor(gvc, str);
        gvrender_polygon(gvc, A, 4, TRUE);      /* filled */
@@ -333,45 +351,165 @@ static void emit_defaults(GVC_t * gvc)
 
 
 /* even if this makes you cringe, at least it's short */
-static void setup_page(GVC_t * gvc, point page)
+static void setup_page(GVC_t * gvc)
 {
     point offset;
     int rot;
     graph_t *g = gvc->g;
 
-    Page++;
-
     /* establish current box in graph coordinates */
-    CB.LL.x = page.x * GP.x;
-    CB.LL.y = page.y * GP.y;
-    CB.UR.x = CB.LL.x + GP.x;
-    CB.UR.y = CB.LL.y + GP.y;
+    gvc->pageBox.LL.x = gvc->pagesArrayElem.x * gvc->pageSize.x;
+    gvc->pageBox.LL.y = gvc->pagesArrayElem.y * gvc->pageSize.y;
+    gvc->pageBox.UR.x = gvc->pageBox.LL.x + gvc->pageSize.x;
+    gvc->pageBox.UR.y = gvc->pageBox.LL.y + gvc->pageSize.y;
 
     /* establish offset to be applied, in graph coordinates */
     if (GD_drawing(g)->landscape == FALSE)
-       offset = pointof(-CB.LL.x, -CB.LL.y);
+       offset = pointof(-gvc->pageBox.LL.x, -gvc->pageBox.LL.y);
     else {
-       offset.x = (page.y + 1) * GP.y;
-       offset.y = -page.x * GP.x;
+       offset.x = (gvc->pagesArrayElem.y + 1) * gvc->pageSize.y;
+       offset.y = -(gvc->pagesArrayElem.x) * gvc->pageSize.x;
     }
     rot = GD_drawing(g)->landscape ? 90 : 0;
 
-    gvrender_begin_page(gvc, page, gvc->job->zoom, rot, offset);
-    emit_background(gvc, CB.LL, CB.UR);
+    gvrender_begin_page(gvc, gvc->job->zoom, rot, offset);
+    emit_background(gvc, gvc->pageBox);
     emit_defaults(gvc);
 }
 
-static int node_in_CB(GVC_t *gvc, node_t * n)
+static boolean node_in_pageBox(GVC_t *gvc, node_t * n)
 {
-    box nb;
+    boxf nb;
 
-    if (gvc->pagesSize == 1)
+    if (gvc->numPages == 1)
        return TRUE;
     nb.LL.x = ND_coord_i(n).x - ND_lw_i(n);
-    nb.LL.y = ND_coord_i(n).y - ND_ht_i(n) / 2;
+    nb.LL.y = ND_coord_i(n).y - ND_ht_i(n) / 2.;
     nb.UR.x = ND_coord_i(n).x + ND_rw_i(n);
-    nb.UR.y = ND_coord_i(n).y + ND_ht_i(n) / 2;
-    return rect_overlap(CB, nb);
+    nb.UR.y = ND_coord_i(n).y + ND_ht_i(n) / 2.;
+    return boxf_overlap(gvc->pageBox, nb);
+}
+
+static int is_natural_number(char *sstr)
+{
+    unsigned char *str = (unsigned char *) sstr;
+    while (*str)
+       if (NOT(isdigit(*str++)))
+           return FALSE;
+    return TRUE;
+}
+
+static int layer_index(GVC_t *gvc, char *str, int all)
+{
+    int i;
+
+    if (streq(str, "all"))
+       return all;
+    if (is_natural_number(str))
+       return atoi(str);
+    if (gvc->layerIDs)
+       for (i = 1; i <= gvc->numLayers; i++)
+           if (streq(str, gvc->layerIDs[i]))
+               return i;
+    return -1;
+}
+
+static int selectedlayer(GVC_t *gvc, char *spec)
+{
+    int n0, n1;
+    unsigned char buf[SMALLBUF];
+    char *w0, *w1;
+    agxbuf xb;
+    int rval = FALSE;
+
+    agxbinit(&xb, SMALLBUF, buf);
+    agxbput(&xb, spec);
+    w1 = w0 = strtok(agxbuse(&xb), gvc->layerDelims);
+    if (w0)
+       w1 = strtok(NULL, gvc->layerDelims);
+    switch ((w0 != NULL) + (w1 != NULL)) {
+    case 0:
+       rval = FALSE;
+       break;
+    case 1:
+       n0 = layer_index(gvc, w0, gvc->layerNum);
+       rval = (n0 == gvc->layerNum);
+       break;
+    case 2:
+       n0 = layer_index(gvc, w0, 0);
+       n1 = layer_index(gvc, w1, gvc->numLayers);
+       if ((n0 < 0) || (n1 < 0))
+           rval = TRUE;
+       else if (n0 > n1) {
+           int t = n0;
+           n0 = n1;
+           n1 = t;
+       }
+       rval = BETWEEN(n0, gvc->layerNum, n1);
+       break;
+    }
+    agxbfree(&xb);
+    return rval;
+}
+
+static int node_in_layer(GVC_t *gvc, graph_t * g, node_t * n)
+{
+    char *pn, *pe;
+    edge_t *e;
+
+    if (gvc->numLayers <= 1)
+       return TRUE;
+    pn = late_string(n, N_layer, "");
+    if (selectedlayer(gvc, pn))
+       return TRUE;
+    if (pn[0])
+       return FALSE;           /* Only check edges if pn = "" */
+    if ((e = agfstedge(g, n)) == NULL)
+       return TRUE;
+    for (e = agfstedge(g, n); e; e = agnxtedge(g, e, n)) {
+       pe = late_string(e, E_layer, "");
+       if ((pe[0] == '\0') || selectedlayer(gvc, pe))
+           return TRUE;
+    }
+    return FALSE;
+}
+
+static int edge_in_layer(GVC_t *gvc, graph_t * g, edge_t * e)
+{
+    char *pe, *pn;
+    int cnt;
+
+    if (gvc->numLayers <= 1)
+       return TRUE;
+    pe = late_string(e, E_layer, "");
+    if (selectedlayer(gvc, pe))
+       return TRUE;
+    if (pe[0])
+       return FALSE;
+    for (cnt = 0; cnt < 2; cnt++) {
+       pn = late_string(cnt < 1 ? e->tail : e->head, N_layer, "");
+       if ((pn[0] == '\0') || selectedlayer(gvc, pn))
+           return TRUE;
+    }
+    return FALSE;
+}
+
+static int clust_in_layer(GVC_t *gvc, graph_t * sg)
+{
+    char *pg;
+    node_t *n;
+
+    if (gvc->numLayers <= 1)
+       return TRUE;
+    pg = late_string(sg, agfindattr(sg, "layer"), "");
+    if (selectedlayer(gvc, pg))
+       return TRUE;
+    if (pg[0])
+       return FALSE;
+    for (n = agfstnode(sg); n; n = agnxtnode(sg, n))
+       if (node_in_layer(gvc, sg, n))
+           return TRUE;
+    return FALSE;
 }
 
 static void emit_node(GVC_t * gvc, node_t * n)
@@ -380,7 +518,7 @@ static void emit_node(GVC_t * gvc, node_t * n)
 
     if (ND_shape(n) == NULL)
        return;
-    if (node_in_layer(n->graph, n) && node_in_CB(gvc, n) && (ND_state(n) != Page)) {
+    if (node_in_layer(gvc, n->graph, n) && node_in_pageBox(gvc, n) && (ND_state(n) != gvc->pageNum)) {
        gvrender_begin_node(gvc, n);
        if (((s = agget(n, "href")) && s[0])
            || ((s = agget(n, "URL")) && s[0])) {
@@ -395,7 +533,7 @@ static void emit_node(GVC_t * gvc, node_t * n)
        }
        gvrender_begin_context(gvc);
        ND_shape(n)->fns->codefn(gvc, n);
-       ND_state(n) = Page;
+       ND_state(n) = gvc->pageNum;
        gvrender_end_context(gvc);
        if (url) {
            gvrender_end_anchor(gvc);
@@ -472,15 +610,17 @@ void emit_attachment(GVC_t * gvc, textlabel_t * lp, splines * spl)
     gvrender_polyline(gvc, A, 3);
 }
 
-static int edge_in_CB(GVC_t *gvc, edge_t * e)
+static boolean edge_in_pageBox(GVC_t *gvc, edge_t * e)
 {
     int i, j, np;
     bezier bz;
-    point *p, pp, sz;
-    box b;
+    point *p;
+    pointf pp, pn;
+    double sx, sy;
+    boxf b;
     textlabel_t *lp;
 
-    if (gvc->pagesSize == 1)
+    if (gvc->numPages == 1)
        return TRUE;
     if (ED_spl(e) == NULL)
        return FALSE;
@@ -488,21 +628,23 @@ static int edge_in_CB(GVC_t *gvc, edge_t * e)
        bz = ED_spl(e)->list[i];
        np = bz.size;
        p = bz.list;
-       pp = p[0];
+       P2PF(p[0],pp);
        for (j = 0; j < np; j++) {
-           if (rect_overlap(CB, mkbox(pp, p[j])))
+           P2PF(p[j],pn);
+           if (boxf_overlap(gvc->pageBox, mkboxf(pp, pn)))
                return TRUE;
-           pp = p[j];
+           pp = pn;
        }
     }
     if ((lp = ED_label(e)) == NULL)
        return FALSE;
-    PF2P(lp->dimen, sz);
-    b.LL.x = lp->p.x - sz.x / 2;
-    b.UR.x = lp->p.x + sz.x / 2;
-    b.LL.y = lp->p.y - sz.y / 2;
-    b.UR.y = lp->p.y + sz.y / 2;
-    return rect_overlap(CB, b);
+    sx = lp->dimen.x / 2.;
+    sy = lp->dimen.y / 2.;
+    b.LL.x = lp->p.x - sx;
+    b.UR.x = lp->p.x + sx;
+    b.LL.y = lp->p.y - sy;
+    b.UR.y = lp->p.y + sy;
+    return boxf_overlap(gvc->pageBox, b);
 }
 
 static void emit_edge(GVC_t * gvc, edge_t * e)
@@ -524,8 +666,8 @@ static void emit_edge(GVC_t * gvc, edge_t * e)
 
 #define SEP 2.0
 
-    if ((edge_in_CB(gvc, e) == FALSE)
-       || (edge_in_layer(e->head->graph, e) == FALSE))
+    if ((edge_in_pageBox(gvc, e) == FALSE)
+       || (edge_in_layer(gvc, e->head->graph, e) == FALSE))
        return;
 
     gvrender_begin_edge(gvc, e);
@@ -699,6 +841,7 @@ static void emit_edge(GVC_t * gvc, edge_t * e)
     gvrender_end_edge(gvc);
 }
 
+#ifdef PAGINATIONBUG
 static double setScale(graph_t * g)
 {
     double xscale, yscale, scale;
@@ -711,6 +854,7 @@ static double setScale(graph_t * g)
     GD_drawing(g)->size.y = scale * GD_bb(g).UR.y;
     return scale;
 }
+#endif
 
 
 /* emit_init
@@ -723,7 +867,7 @@ void emit_init(GVC_t * gvc, graph_t * g)
     double X, Y, Z, x, y;
     point size = GD_drawing(g)->size;
     point UR = GD_bb(g).UR;
-#if 1
+#ifdef PAGINATIONBUG
     double scale;
 #endif
 
@@ -732,22 +876,27 @@ void emit_init(GVC_t * gvc, graph_t * g)
     /* determine final drawing size and scale to apply. */
     /* N.B. size given by user is not rotated by landscape mode */
     /* start with "natural" size of layout */
-#if 1
+#ifdef PAGINATIONBUG
     /* FIXME - this version still needed by psgen.c*/
     scale = GD_drawing(g)->scale = 1.0;
     if (GD_drawing(g)->size.x > 0) {    /* was given by user... */
         if ((GD_drawing(g)->size.x < GD_bb(g).UR.x)     /* drawing is too big... */
             ||(GD_drawing(g)->size.y < GD_bb(g).UR.y)) {
             scale = setScale(g);
-        } else if (GD_drawing(g)->filled) {
+        }
+       else if (GD_drawing(g)->filled) {
             if ((GD_drawing(g)->size.x > GD_bb(g).UR.x) /* drawing is too small... */
                 &&(GD_drawing(g)->size.y > GD_bb(g).UR.y)) {
-                scale = setScale(g);
+               scale = setScale(g);
             }
-        } else
+        }
+       else {
             GD_drawing(g)->size = GD_bb(g).UR;
-    } else
+       }
+    }
+    else {
         GD_drawing(g)->size = GD_bb(g).UR;
+    }
 #endif
 
     Z = 1.0;
@@ -772,9 +921,9 @@ void emit_init(GVC_t * gvc, graph_t * g)
        late_double(g->proto->n, N_fontsize, DEFAULT_FONTSIZE,
                    MIN_FONTSIZE);
 
-    setup_layering(gvc, g);
+    init_layering(gvc, g);
 
-    setup_pagination(gvc, g);
+    init_job_pagination(gvc, g);
 
     gvrender_begin_job(gvc, Lib, X, Y, Z, x, y, GD_drawing(g)->dpi);
 }
@@ -784,28 +933,36 @@ void emit_deinit(GVC_t * gvc)
     gvrender_end_job(gvc);
 }
 
-static int validpage(GVC_t *gvc, point page)
+static void init_job_margin(GVC_t *gvc)
 {
-    return ((page.x >= 0) && (page.x < gvc->pagesArraySize.x)
-           && (page.y >= 0) && (page.y < gvc->pagesArraySize.y));
-}
-
-static point pageincr(GVC_t *gvc, point page)
-{
-    page = add_points(page, gvc->pagesArrayMinor);
-    if (validpage(gvc, page) == FALSE) {
-       if (gvc->pagesArrayMajor.y)
-           page.x = gvc->pagesArrayFirst.x;
-       else
-           page.y = gvc->pagesArrayFirst.y;
-       page = add_points(page, gvc->pagesArrayMajor);
+    gvrender_job_t *job = gvc->job;
+    
+    if (gvc->graph_sets_margin) {
+       job->margin = gvc->margin;
+    }
+    else {
+        /* set default margins depending on format */
+        switch (gvc->job->output_lang) {
+        case GVRENDER_PLUGIN:
+            job->margin.x = job->margin.y = job->render_features->default_margin;
+            break;
+        case POSTSCRIPT: case PDF: case HPGL: case PCL: case MIF:
+        case METAPOST: case FIG: case VTX: case ATTRIBUTED_DOT:
+        case PLAIN: case PLAIN_EXT: case QPDF:
+            job->margin.x = job->margin.y = DEFAULT_MARGIN;
+            break;
+        case CANONICAL_DOT:
+            job->margin.x = job->margin.y = 0;
+            break;
+        default:
+            job->margin.x = job->margin.y = DEFAULT_EMBED_MARGIN;
+            break;
+        }
     }
-    return page;
 }
 
 void emit_graph(GVC_t * gvc, graph_t * g, int flags)
 {
-    point curpage;
     graph_t *sg;
     node_t *n;
     edge_t *e;
@@ -813,18 +970,11 @@ void emit_graph(GVC_t * gvc, graph_t * g, int flags)
     char *str, *colors;
     char *s, *url = NULL, *tooltip = NULL, *target = NULL;
 
-/* FIXME - shouldn't need this again */
-    setup_pagination(gvc, g);
+    init_job_margin(gvc);
 
-#if 0
-/* FIXME - apparently zoom is not set yet */
-    gvc->clip.UR.x = ROUND(gvc->focus.x + (gvc->width+1) / (gvc->zoom * 2.));
-    gvc->clip.UR.y = ROUND(gvc->focus.y + (gvc->height+1) / (gvc->zoom * 2.));
-    gvc->clip.LL.x = ROUND(gvc->focus.x - (gvc->width+1) / (gvc->zoom * 2.));
-    gvc->clip.LL.y = ROUND(gvc->focus.y - (gvc->height+1) / (gvc->zoom * 2.));
-#endif
+    init_job_pagination(gvc, g);
 
-    gvrender_begin_graph(gvc, g, PB, PFC);
+    gvrender_begin_graph(gvc, g);
     if (flags & EMIT_COLORS) {
        gvrender_set_fillcolor(gvc, DEFAULT_FILL);
        if (((str = agget(g, "bgcolor")) != 0) && str[0])
@@ -866,14 +1016,12 @@ void emit_graph(GVC_t * gvc, graph_t * g, int flags)
        }
     }
 
-    Layer = 1;
-    do {
-       if (Nlayers > 0)
-           gvrender_begin_layer(gvc, LayerID[Layer], Layer, Nlayers);
-       for (curpage = gvc->pagesArrayFirst; validpage(gvc, curpage);
-            curpage = pageincr(gvc, curpage)) {
+    for (firstlayer(gvc); validlayer(gvc); nextlayer(gvc)) {
+       if (gvc->numLayers > 1)
+           gvrender_begin_layer(gvc);
+       for (firstpage(gvc); validpage(gvc); nextpage(gvc)) {
+           setup_page(gvc);
            Obj = NONE;
-           setup_page(gvc, curpage);
            if (((s = agget(g, "href")) && s[0])
                || ((s = agget(g, "URL")) && s[0])) {
                url = strdup_and_subst_graph(s, g);
@@ -975,16 +1123,15 @@ void emit_graph(GVC_t * gvc, graph_t * g, int flags)
            }
            gvrender_end_page(gvc);
        }
-       if (Nlayers > 0)
+       if (gvc->numLayers > 1)
            gvrender_end_layer(gvc);
-       Layer++;
-    } while (Layer <= Nlayers);
+    }
     gvrender_end_graph(gvc);
 }
 
 void emit_eof(GVC_t * gvc)
 {
-    if (Page > 0) {
+    if (gvc->pageNum > 0) {
         emit_deinit(gvc);
        emit_once_reset();
     }
@@ -1002,7 +1149,7 @@ void emit_clusters(GVC_t * gvc, Agraph_t * g, int flags)
 
     for (c = 1; c <= GD_n_cluster(g); c++) {
        sg = GD_clust(g)[c];
-       if (clust_in_layer(sg) == FALSE)
+       if (clust_in_layer(gvc, sg) == FALSE)
            continue;
        /* when mapping, detect events on clusters after sub_clusters */
        if (flags & EMIT_CLUSTERS_LAST) {
@@ -1098,128 +1245,6 @@ void emit_clusters(GVC_t * gvc, Agraph_t * g, int flags)
     }
 }
 
-int node_in_layer(graph_t * g, node_t * n)
-{
-    char *pn, *pe;
-    edge_t *e;
-
-    if (Nlayers <= 0)
-       return TRUE;
-    pn = late_string(n, N_layer, "");
-    if (selectedlayer(pn))
-       return TRUE;
-    if (pn[0])
-       return FALSE;           /* Only check edges if pn = "" */
-    if ((e = agfstedge(g, n)) == NULL)
-       return TRUE;
-    for (e = agfstedge(g, n); e; e = agnxtedge(g, e, n)) {
-       pe = late_string(e, E_layer, "");
-       if ((pe[0] == '\0') || selectedlayer(pe))
-           return TRUE;
-    }
-    return FALSE;
-}
-
-int edge_in_layer(graph_t * g, edge_t * e)
-{
-    char *pe, *pn;
-    int cnt;
-
-    if (Nlayers <= 0)
-       return TRUE;
-    pe = late_string(e, E_layer, "");
-    if (selectedlayer(pe))
-       return TRUE;
-    if (pe[0])
-       return FALSE;
-    for (cnt = 0; cnt < 2; cnt++) {
-       pn = late_string(cnt < 1 ? e->tail : e->head, N_layer, "");
-       if ((pn[0] == '\0') || selectedlayer(pn))
-           return TRUE;
-    }
-    return FALSE;
-}
-
-int clust_in_layer(graph_t * sg)
-{
-    char *pg;
-    node_t *n;
-
-    if (Nlayers <= 0)
-       return TRUE;
-    pg = late_string(sg, agfindattr(sg, "layer"), "");
-    if (selectedlayer(pg))
-       return TRUE;
-    if (pg[0])
-       return FALSE;
-    for (n = agfstnode(sg); n; n = agnxtnode(sg, n))
-       if (node_in_layer(sg, n))
-           return TRUE;
-    return FALSE;
-}
-
-int is_natural_number(char *sstr)
-{
-    unsigned char *str = (unsigned char *) sstr;
-    while (*str)
-       if (NOT(isdigit(*str++)))
-           return FALSE;
-    return TRUE;
-}
-
-static int layer_index(char *str, int all)
-{
-    int i;
-
-    if (streq(str, "all"))
-       return all;
-    if (is_natural_number(str))
-       return atoi(str);
-    if (LayerID)
-       for (i = 1; i <= Nlayers; i++)
-           if (streq(str, LayerID[i]))
-               return i;
-    return -1;
-}
-
-int selectedlayer(char *spec)
-{
-    int n0, n1;
-    unsigned char buf[SMALLBUF];
-    char *w0, *w1;
-    agxbuf xb;
-    int rval = FALSE;
-
-    agxbinit(&xb, SMALLBUF, buf);
-    agxbput(&xb, spec);
-    w1 = w0 = strtok(agxbuse(&xb), Layerdelims);
-    if (w0)
-       w1 = strtok(NULL, Layerdelims);
-    switch ((w0 != NULL) + (w1 != NULL)) {
-    case 0:
-       rval = FALSE;
-       break;
-    case 1:
-       n0 = layer_index(w0, Layer);
-       rval = (n0 == Layer);
-       break;
-    case 2:
-       n0 = layer_index(w0, 0);
-       n1 = layer_index(w1, Nlayers);
-       if ((n0 < 0) || (n1 < 0))
-           rval = TRUE;
-       else if (n0 > n1) {
-           int t = n0;
-           n0 = n1;
-           n1 = t;
-       }
-       rval = BETWEEN(n0, Layer, n1);
-       break;
-    }
-    agxbfree(&xb);
-    return rval;
-}
-
 static int style_delim(int c)
 {
     switch (c) {
index 7c7b263bc9b5c68596d6c5e128b6b906597d54b2..039ff1cbcc2cc29dfb8d3ab6f9c9bf48bd599920 100644 (file)
 
 #define P2PF(p, pf) (pf.x = p.x, pf.y = p.y)
 #define PF2P(pf, p) (p.x = ROUND (pf.x), p.y = ROUND (pf.y))
+#define B2BF(b, bf) (bf.LL.x = b.LL.x, bf.LL.y = b.LL.y, bf.UR.x = b.UR.x, bf.UR.y = b.UR.y)
+#define BF2B(bf, b) (b.LL.x = ROUND (bf.LL.x), b.LL.y = ROUND (bf.LL.y), b.UR.x = ROUND (bf.UR.x), b.UR.y = ROUND (bf.UR.y))
 
 #define XPAD(d) ((d).x += 4*GAP)
 #define YPAD(d) ((d).y += 2*GAP)
index d248364a9b0d1ccd329ffceaf6666da363dfbf60..9d699bd6ddfb8bf5b617950eb68bce56110e3204 100644 (file)
@@ -35,69 +35,33 @@ static void extend_attrs(GVC_t * gvc);
 #define Y(y) (y_invert ? (y_off - (y)) : (y))
 #define YF(y) (y_invert ? (yf_off - (y)) : (y))
 
-void dotneato_set_margins(GVC_t * gvc, graph_t * g)
+static void graph_sets_margin(GVC_t * gvc, graph_t * g)
 {
     double xf, yf;
     char *p;
     int i;
 
     /* margins */
+    gvc->graph_sets_margin = FALSE;
     if ((p = agget(g, "margin"))) {
-       i = sscanf(p, "%lf,%lf", &xf, &yf);
-       if (i > 0)
-           GD_drawing(g)->margin.x = GD_drawing(g)->margin.y = POINTS(xf);
-       if (i > 1)
-           GD_drawing(g)->margin.y = POINTS(yf);
-    } else {
-       /* set default margins depending on format */
-       switch (gvc->job->output_lang) {
-       case GVRENDER_PLUGIN:
-           GD_drawing(g)->margin.x = GD_drawing(g)->margin.y =
-               gvc->job->render_features->default_margin;
-           break;
-       case GIF:
-       case PNG:
-       case JPEG:
-       case WBMP:
-       case GD:
-       case memGD:
-       case GD2:
-       case ISMAP:
-       case IMAP:
-       case CMAP:
-       case CMAPX:
-       case VRML:
-       case DIA:
-       case SVG:
-       case SVGZ:
-       case QEPDF:
-           GD_drawing(g)->margin.x = GD_drawing(g)->margin.y =
-               DEFAULT_EMBED_MARGIN;
-           break;
-       case POSTSCRIPT:
-       case PDF:
-       case HPGL:
-       case PCL:
-       case MIF:
-       case METAPOST:
-       case FIG:
-       case VTX:
-       case ATTRIBUTED_DOT:
-       case PLAIN:
-       case PLAIN_EXT:
-       case QPDF:
-           GD_drawing(g)->margin.x = GD_drawing(g)->margin.y =
-               DEFAULT_MARGIN;
-           break;
-       case CANONICAL_DOT:
-           break;
-       default:
-           if (gvc->job->output_lang >= QBM_FIRST
-               && gvc->job->output_lang < QBM_LAST)
-               GD_drawing(g)->margin.x = GD_drawing(g)->margin.y =
-                   DEFAULT_EMBED_MARGIN;
-           break;
-       }
+        i = sscanf(p, "%lf,%lf", &xf, &yf);
+        if (i > 0) {
+            gvc->margin.x = gvc->margin.y = xf * POINTS_PER_INCH;
+            if (i > 1)
+                gvc->margin.y = yf * POINTS_PER_INCH;
+            gvc->graph_sets_margin = TRUE;
+        }
+    }
+}
+
+static void graph_sets_page(GVC_t * gvc, graph_t * g)
+{
+    gvc->graph_sets_page = FALSE;
+    P2PF(GD_drawing(g)->page, gvc->page);
+    P2PF(GD_bb(g).LL,gvc->bb.LL);
+    P2PF(GD_bb(g).UR,gvc->bb.UR);
+    if ((GD_drawing(g)->page.x > 0) && (GD_drawing(g)->page.y > 0)) {
+       gvc->graph_sets_page = TRUE;
     }
 }
 
@@ -118,75 +82,75 @@ static int chkOrder(graph_t * g)
     return 0;
 }
 
-void dotneato_write_one(GVC_t * gvc, graph_t * g)
+static int lang_sets_flags(gvrender_job_t * job, graph_t * g)
 {
-    gvrender_job_t *job = gvc->job;
     int flags;
 
-    gvc->g = g;
-#ifndef DISABLE_CODEGENS
-    Output_file = job->output_file;
-    Output_lang = job->output_lang;
-#endif
-    dotneato_set_margins(gvc, g);
-    emit_init(gvc, g);
-    if (NOT(gvrender_features(gvc) & GVRENDER_DOES_MULTIGRAPH_OUTPUT_FILES)
-#ifndef DISABLE_CODEGENS
-/* FIXME - bad hack until feaures supported in codegens */
-       && job->codegen != &PS_CodeGen
-#ifdef QUARTZ_RENDER
-       && job->codegen != &QPDF_CodeGen && job->codegen != &QEPDF_CodeGen
-#endif
-#endif
-       )
-       emit_reset(gvc, g);  /* FIXME - split into emit_init & page reset */
-    switch (gvc->job->output_lang) {
+    switch (job->output_lang) {
     case GVRENDER_PLUGIN:
-       flags = chkOrder(g);
-       flags |= job->render_features->flags;
-       gvemit_graph(gvc, g, flags);
+       flags = chkOrder(g) | job->render_features->flags;
        break;
     case POSTSCRIPT:
-    case PDF:
-    case HPGL:
-    case PCL:
-    case MIF:
-    case PIC_format:
-    case GIF:
-    case PNG:
-    case JPEG:
-    case WBMP:
-    case GD:
-    case memGD:
-    case GD2:
-    case VRML:
-    case METAPOST:
-    case SVG:
-    case SVGZ:
-    case QPDF:
-    case QEPDF:
-       emit_graph(gvc, g, chkOrder(g));
+        flags = chkOrder(g) | GVRENDER_DOES_MULTIGRAPH_OUTPUT_FILES;
        break;
-    case ISMAP:
-    case IMAP:
-    case CMAP:
-    case CMAPX:
+    case ISMAP: case IMAP: case CMAP: case CMAPX:
        /* output in breadth first graph walk order, but 
         * with nodes edges and nested clusters before
         * clusters */
-       emit_graph(gvc, g, EMIT_CLUSTERS_LAST);
+       flags = EMIT_CLUSTERS_LAST;
        break;
     case FIG:
        /* output color definition objects first */
-       emit_graph(gvc, g, EMIT_COLORS);
+       flags = EMIT_COLORS;
        break;
     case VTX:
        /* output sorted, i.e. all nodes then all edges */
-       emit_graph(gvc, g, EMIT_SORTED);
+       flags = EMIT_SORTED;
        break;
     case DIA:
        /* output in preorder traversal of the graph */
-       emit_graph(gvc, g, EMIT_PREORDER);
+       flags = EMIT_PREORDER;
+       break;
+    case EXTENDED_DOT: case ATTRIBUTED_DOT: case CANONICAL_DOT:
+    case PLAIN: case PLAIN_EXT:
+       flags = 0;
+       break;
+    default:
+       flags = chkOrder(g);
+       break;
+    }
+    return flags;
+}
+
+void dotneato_write_one(GVC_t * gvc, graph_t * g)
+{
+    gvrender_job_t *job = gvc->job;
+    int flags;
+
+    gvc->g = g;
+#ifndef DISABLE_CODEGENS
+    Output_file = job->output_file;
+    Output_lang = job->output_lang;
+#endif
+
+    graph_sets_margin(gvc, g);
+    graph_sets_page(gvc, g);
+    flags = lang_sets_flags(job, g);
+    emit_init(gvc, g);
+
+    if (! (flags & GVRENDER_DOES_MULTIGRAPH_OUTPUT_FILES))
+       emit_reset(gvc, g);  /* FIXME - split into emit_init & page reset */
+
+    switch (gvc->job->output_lang) {
+    case GVRENDER_PLUGIN:
+       gvemit_graph(gvc, g, flags);
+       break;
+    case POSTSCRIPT: case PDF: case HPGL: case PCL: case MIF:
+    case PIC_format: case GIF: case PNG: case JPEG: case WBMP:
+    case GD: case memGD: case GD2: case VRML: case METAPOST:
+    case SVG: case SVGZ: case QPDF: case QEPDF: case ISMAP:
+    case IMAP: case CMAP: case CMAPX: case FIG: case VTX: case DIA:
+       emit_graph(gvc, g, flags);
        break;
     case EXTENDED_DOT:
        attach_attrs(g);
@@ -203,20 +167,18 @@ void dotneato_write_one(GVC_t * gvc, graph_t * g)
        agwrite(g, gvc->job->output_file);
        break;
     case PLAIN:
-       /* attach_attrs(g);  */
        write_plain(gvc, gvc->job->output_file);
        break;
     case PLAIN_EXT:
-       /* attach_attrs(g);  */
        write_plain_ext(gvc, gvc->job->output_file);
        break;
     default:
        if (gvc->job->output_lang >= QBM_FIRST
            && gvc->job->output_lang < QBM_LAST)
-           emit_graph(gvc, g, chkOrder(g));
+           emit_graph(gvc, g, flags);
        break;
-
     }
+
     fflush(gvc->job->output_file);
 #if 0
     emit_deinit(gvc);
index 49c0ff9c78a85d5a226078276c1b37d89636bd4f..a6677e6825cd42179fd4338f85531454db83ee2f 100644 (file)
@@ -25,6 +25,7 @@ extern "C" {
 
     extern void add_box(path *, box);
     extern point add_points(point, point);
+    extern pointf add_pointfs(pointf, pointf);
     extern void arrow_flags(Agedge_t * e, int *sflag, int *eflag);
     extern void arrow_gen(GVC_t * gvc, point p, point u, double scale,
                          int flag);
@@ -43,10 +44,11 @@ extern "C" {
                            boolean left_inside);
     extern shape_desc *bind_shape(char *name, node_t *);
     extern box boxof(int, int, int, int);
+    extern boolean box_overlap(box, box);
+    extern boolean boxf_overlap(boxf, boxf);
     extern void cat_libfile(FILE *, char **, char **);
     extern void clip_and_install(edge_t *, edge_t *, point *, int,
                                 splineInfo *);
-    extern int clust_in_layer(Agraph_t *);
     extern char *canontoken(char *str);
     extern void colorxlate(char *str, color_t * color,
                           color_type_t target_type);
@@ -69,7 +71,6 @@ extern "C" {
     extern void dotneato_terminate(GVC_t * gvc);
     extern void dotneato_write(GVC_t * gvc, graph_t *g);
     extern void dotneato_write_one(GVC_t * gvc, graph_t *g);
-    extern int edge_in_layer(Agraph_t *, Agedge_t *);
     extern double elapsed_sec(void);
     extern void enqueue(queue *, Agnode_t *);
     extern void enqueue_neighbors(queue *, Agnode_t *, int);
@@ -113,7 +114,6 @@ extern "C" {
     extern point image_size(graph_t * g, char *shapefile);
     extern void init_ugraph(graph_t * g);
     extern point invflip_pt(point p, int rankdir);
-    extern int is_natural_number(char *);
     extern boolean isPolygon(node_t *);
     extern int late_attr(void *, char *);
     extern int late_bool(void *, Agsym_t *, int);
@@ -137,11 +137,11 @@ extern "C" {
     extern void map_edge(Agedge_t *);
     extern point map_point(point);
     extern box mkbox(point, point);
+    extern boxf mkboxf(pointf, pointf);
     extern point neato_closest(splines * spl, point p);
     extern bezier *new_spline(edge_t * e, int sz);
     extern queue *new_queue(int);
     extern Agraph_t *next_input_graph(void);
-    extern int node_in_layer(Agraph_t *, node_t *);
     extern void osize_label(textlabel_t *, int *, int *, int *, int *);
     extern char **parse_style(char *s);
     extern void place_graph_label(Agraph_t *);
@@ -152,12 +152,10 @@ extern "C" {
     extern char *ps_string(char *s);
     extern void rank(graph_t * g, int balance, int maxiter);
     extern void rec_attach_bb(Agraph_t *);
-    extern int rect_overlap(box, box);
     extern void routesplinesinit(void);
     extern point *routesplines(path *, int *);
     extern void routesplinesterm(void);
     extern char *safefile(char *shapefilename);
-    extern int selectedlayer(char *);
     extern void setup_graph(GVC_t * gvc, graph_t * g);
     extern shape_kind shapeOf(node_t *);
     extern void shape_clip(node_t * n, point curve[4], edge_t * e);
@@ -188,6 +186,7 @@ extern "C" {
 #   define extern __EXPORT__
 #endif
     extern point sub_points(point, point);
+    extern pointf sub_pointfs(pointf, pointf);
 
     extern void toggle(int);
     extern int test_toggle();
index bc25342a60da3b9f166680486b63d292fda5363f..b039ffed6d74b08213090f22409d000cade84b55 100644 (file)
@@ -41,10 +41,22 @@ extern "C" {
 
     typedef struct htmllabel_t htmllabel_t;
 
+    typedef struct point {
+       int x, y;
+    } point;
+
     typedef struct pointf {
        double x, y;
     } pointf;
 
+    typedef struct box {
+       point LL, UR;
+    } box;
+
+    typedef struct boxf {
+       pointf LL, UR;
+    } boxf;
+
     typedef struct inside_t {
        pointf *p;
        double *r;
@@ -52,14 +64,6 @@ extern "C" {
        edge_t *e;
     } inside_t;
 
-    typedef struct point {
-       int x, y;
-    } point;
-
-    typedef struct box {
-       point LL, UR;
-    } box;
-
     typedef struct port {      /* internal edge endpoint specification */
        point p;                /* aiming point */
        double theta;           /* slope in radians */
index 553acc3e3a7241bf9e1b7cf27937665b1f094884..f9782d67acc6243b2ea7acc469625dd614a69bcc 100644 (file)
@@ -293,6 +293,27 @@ box mkbox(point p0, point p1)
     return rv;
 }
 
+boxf mkboxf(pointf p0, pointf p1)
+{
+    boxf rv;
+
+    if (p0.x < p1.x) {
+       rv.LL.x = p0.x;
+       rv.UR.x = p1.x;
+    } else {
+       rv.LL.x = p1.x;
+       rv.UR.x = p0.x;
+    }
+    if (p0.y < p1.y) {
+       rv.LL.y = p0.y;
+       rv.UR.y = p1.y;
+    } else {
+       rv.LL.y = p1.y;
+       rv.UR.y = p0.y;
+    }
+    return rv;
+}
+
 point add_points(point p0, point p1)
 {
     p0.x += p1.x;
@@ -307,6 +328,20 @@ point sub_points(point p0, point p1)
     return p0;
 }
 
+pointf add_pointfs(pointf p0, pointf p1)
+{
+    p0.x += p1.x;
+    p0.y += p1.y;
+    return p0;
+}
+
+pointf sub_pointfs(pointf p0, pointf p1)
+{
+    p0.x -= p1.x;
+    p0.y -= p1.y;
+    return p0;
+}
+
 /* from Glassner's Graphics Gems */
 #define W_DEGREE 5
 
@@ -542,7 +577,15 @@ void cat_libfile(FILE * ofp, char **arglib, char **stdlib)
     }
 }
 
-int rect_overlap(box b0, box b1)
+boolean box_overlap(box b0, box b1)
+{
+    if ((b0.UR.x < b1.LL.x) || (b1.UR.x < b0.LL.x)
+       || (b0.UR.y < b1.LL.y) || (b1.UR.y < b0.LL.y))
+       return FALSE;
+    return TRUE;
+}
+
+boolean boxf_overlap(boxf b0, boxf b1)
 {
     if ((b0.UR.x < b1.LL.x) || (b1.UR.x < b0.LL.x)
        || (b0.UR.y < b1.LL.y) || (b1.UR.y < b0.LL.y))
index 6fe596334b0f1db6de029cfd5cff6cc696d2056b..8c6f57c67d61ced2d816f0a606c8217243b63252 100644 (file)
@@ -27,10 +27,6 @@ typedef enum {
 
 #define NDIM     2
 
-typedef struct {
-    pointf LL, UR;
-} boxf;
-
 typedef struct bport_s {
     edge_t *e;
     node_t *n;
index 96467ac9f9d158567716eeec84cc1b5705120aa6..1f2186310359ac805bf0f464e85f42ef844a3762 100644 (file)
@@ -78,14 +78,11 @@ extern "C" {
     extern void gvrender_begin_job(GVC_t * gvc, char **lib, double X, double Y, double Z,
                                   double x, double y, int dpi);
     extern void gvrender_end_job(GVC_t * gvc);
-    extern void gvrender_begin_graph(GVC_t * gvc, graph_t * g, box bb,
-                                    point pb);
+    extern void gvrender_begin_graph(GVC_t * gvc, graph_t * g);
     extern void gvrender_end_graph(GVC_t * gvc);
-    extern void gvrender_begin_page(GVC_t * gvc, point page, double scale,
-                                   int rot, point offset);
+    extern void gvrender_begin_page(GVC_t * gvc, double scale, int rot, point offset);
     extern void gvrender_end_page(GVC_t * gvc);
-    extern void gvrender_begin_layer(GVC_t * gvc, char *layerName, int n,
-                                    int nLayers);
+    extern void gvrender_begin_layer(GVC_t * gvc);
     extern void gvrender_end_layer(GVC_t * gvc);
     extern void gvrender_begin_cluster(GVC_t * gvc, graph_t * sg);
     extern void gvrender_end_cluster(GVC_t * gvc);
index 6c487b7e14f174968216fffab306b14b238ab5c8..042382ecfe6620d592a9b0ef0031c906fe38f556 100644 (file)
@@ -53,8 +53,8 @@ extern "C" {
 #define GVRENDER_X11_EVENTS (1<<10)
 
     typedef struct {
+       double default_margin; /* points */
        int flags;
-       int default_margin;
        int default_dpi;
        char **knowncolors;
        int sz_knowncolors;
@@ -86,26 +86,24 @@ extern "C" {
         graph_t *g;            /* parent graph */
         int flags;             /* emit_graph flags */
 
+        pointf margin;         /* job-specific margin */
+       boxf pageBox;           /* drawable region in device coords */
+                               /* basically width*height - margins */
+       pointf pageBoxCentered; /* device page box for centering */
+
         unsigned int width;     /* width in pixels */
         unsigned int height;    /* height in pixels */
        int dpi;                /* resolution pixels-per-inch */
        int rot;                /* rotation */
        double zoom;            /* viewport zoom factor */
        pointf focus;           /* viewport focus in graph units */
-//     pointf pointer;         /* pointer position in graph units */
-//     boxf clip;              /* clip region in graph units */
-
+#if 0
+       pointf pointer;         /* pointer position in graph units */
+#endif
+       boxf clip;              /* clip region in graph units */
+       point offset;
        pointf compscale;       /* composite device scale incl: scale, zoom, dpi, y_goes_down */
        
-        /* gvrender_begin_page */
-       point pagesArrayElem;   /* 2D coord of current page - 0,0 based */
-        int   pagesElem;       /* 1D index of current page - 0 based */
-       point offset;
-
-       /* gvrender_begin_layer() */
-       int layer;
-       int nLayers;
-
        boolean fit_mode, needs_refresh, click, active, has_grown;
 
        void *window;           /* display-specific data for gvrender plugin */
@@ -153,19 +151,32 @@ extern "C" {
 
        char **lib;
 
+       pointf margin, page;
+       boxf bb;
+       boolean graph_sets_margin, graph_sets_page;
+
         /* pagination */
-       point pagesArraySize;   /* 2D size of page array */
-       point pagesArrayFirst;  /* 2D starting corner in */
-       point pagesArrayMajor;  /* 2D major increment */
-       point pagesArrayMinor;  /* 2D minor increment */
-        int   pagesSize;       /* 1D size of page array */
+       point   pagesArraySize;  /* 2D size of page array */
+       point   pagesArrayFirst; /* 2D starting corner in */
+       point   pagesArrayMajor; /* 2D major increment */
+       point   pagesArrayMinor; /* 2D minor increment */
+       point   pagesArrayElem;  /* 2D coord of current page - 0,0 based */
+        int    numPages;        /* number of pages */
+        int    pageNum;         /* current page - 1 based */
+       pointf  pageSize;        /* page size in graph coords */
+       boxf    pageBox;         /* page box in graph coords */
+
+       /* layers */
+       char *layerDelims;      /* delimiters in layer names */
+       char *layers;           /* null delimited list of layer names */
+       char **layerIDs;        /* array of layer names */
+       int numLayers;          /* number of layers */
+       int layerNum;           /* current layer - 1 based*/
 
        /* gvrender_begin_graph() */
        graph_t *g;
 
-       box bb;                 /* graph bounding box (what units???) */
        point pb;               /* page size - including margins (inches) */
-       point margin;           /* page margins (inches) */
 
        gvstyle_t styles[MAXNEST]; /* style stack - reused by each job */
        int SP;
index f92dd3e1a9d66681676b188078adebcf09f0510d..41ae115063eadd8aa2578c0f075f063d38a1e32f 100644 (file)
@@ -29,9 +29,10 @@ extern "C" {
        void (*end_job) (gvrender_job_t * job);
        void (*begin_graph) (gvrender_job_t * job, char *graphname);
        void (*end_graph) (gvrender_job_t * job);
-       void (*begin_page) (gvrender_job_t * job, char *pagename);
-       void (*end_page) (gvrender_job_t * job);
-       void (*begin_layer) (gvrender_job_t * job, char *layername);
+       void (*begin_page) (gvrender_job_t * job, char *pagename, point pagesArrayElem, int pageNum, int numPages);
+       void (*end_page) (gvrender_job_t * job, point pagesArrayElem, int pageNum, int numPages);
+       void (*begin_layer) (gvrender_job_t * job, char *layername,
+                            int layerNum, int numLayers);
        void (*end_layer) (gvrender_job_t * job);
        void (*begin_cluster) (gvrender_job_t * job, char *clustername, long id);
        void (*end_cluster) (gvrender_job_t * job);
index 44f1bc7980aaf3dc41e457e67402f09957ae6b44..4117e0458996a9f69543fbbc28bba432a8b62b00 100644 (file)
@@ -153,7 +153,7 @@ void gvrender_begin_job(GVC_t * gvc, char **lib, double X, double Y, double Z, d
     else {
        codegen_t *cg = job->codegen;
 
-       if (cg && cg->begin_job && job->pagesElem == 0)
+       if (cg && cg->begin_job && gvc->pageNum == 1)
            cg->begin_job(gvc->job->output_file, gvc->g, lib, gvc->user,
                          gvc->info, gvc->pagesArraySize);
     }
@@ -233,22 +233,27 @@ static void gvrender_resolve_color(gvrender_features_t * features,
     }
 }
 
-void gvrender_begin_graph(GVC_t * gvc, graph_t * g, box bb, point pb)
+void gvrender_begin_graph(GVC_t * gvc, graph_t * g)
 {
     gvrender_job_t *job = gvc->job;
     gvrender_engine_t *gvre = job->render_engine;
     char *str;
+    double sx, sy;
 
     gvc->g = g;
-    gvc->bb = bb;
-    gvc->pb = pb;
 
     if (gvre) {
        job->compscale.x = job->zoom * job->dpi / POINTS_PER_INCH;
-       job->compscale.y =
-           job->compscale.x *
+       job->compscale.y = job->compscale.x *
            ((job->render_features->flags & GVRENDER_Y_GOES_DOWN) ? -1.0 : 1.0);
 
+        sx = job->width / (job->zoom * 2.);
+        sy = job->height / (job->zoom * 2.);
+       job->clip.UR.x = job->focus.x + sx;
+       job->clip.UR.y = job->focus.y + sy;
+       job->clip.LL.x = job->focus.x - sx;
+       job->clip.LL.y = job->focus.y - sy;
+
        /* render specific init */
        if (gvre->begin_graph)
            gvre->begin_graph(job, g->name);
@@ -276,9 +281,14 @@ void gvrender_begin_graph(GVC_t * gvc, graph_t * g, box bb, point pb)
 #ifndef DISABLE_CODEGENS
     else {
        codegen_t *cg = job->codegen;
+       box bb;
+       point pb;
+       
+       PF2P(gvc->bb.LL,bb.LL);
+       PF2P(gvc->bb.UR,bb.UR);
 
        if (cg && cg->begin_graph)
-           cg->begin_graph(gvc, g, bb, pb);
+           cg->begin_graph(gvc, g, bb, gvc->pb);
     }
 #endif
 }
@@ -298,30 +308,26 @@ void gvrender_end_graph(GVC_t * gvc)
            cg->end_graph();
     }
 #endif
-    gvc->bb = b0;
-    gvc->pb = p0;
 }
 
-void gvrender_begin_page(GVC_t * gvc, point page, double scale, int rot,
-                        point offset)
+void gvrender_begin_page(GVC_t * gvc, double scale, int rot, point offset)
 {
     gvrender_job_t *job = gvc->job;
     gvrender_engine_t *gvre = job->render_engine;
 
-    job->pagesArrayElem = page;
-    job->pagesElem = page.x + page.y * gvc->pagesArraySize.x + 1;
-
 //    gvc->scale = scale;
     job->rot = rot;
 //    gvc->offset = offset;
     if (gvre && gvre->begin_page)
-       gvre->begin_page(job, gvc->g->name);
+       gvre->begin_page(job, gvc->g->name,
+                         gvc->pagesArrayElem, gvc->pageNum, gvc->numPages);
+
 #ifndef DISABLE_CODEGENS
     else {
        codegen_t *cg = job->codegen;
 
        if (cg && cg->begin_page)
-           cg->begin_page(gvc->g, page, scale, rot, offset);
+           cg->begin_page(gvc->g, gvc->pagesArrayElem, scale, rot, offset);
     }
 #endif
 }
@@ -332,7 +338,7 @@ void gvrender_end_page(GVC_t * gvc)
     gvrender_engine_t *gvre = job->render_engine;
 
     if (gvre && gvre->end_page)
-       gvre->end_page(job);
+       gvre->end_page(job, gvc->pagesArrayElem, gvc->pageNum, gvc->numPages);
 #ifndef DISABLE_CODEGENS
     else {
        codegen_t *cg = job->codegen;
@@ -343,22 +349,19 @@ void gvrender_end_page(GVC_t * gvc)
 #endif
 }
 
-void gvrender_begin_layer(GVC_t * gvc, char *layername, int layer,
-                         int nLayers)
+void gvrender_begin_layer(GVC_t * gvc)
 {
     gvrender_job_t *job = gvc->job;
     gvrender_engine_t *gvre = job->render_engine;
 
-    job->layer = layer;
-    job->nLayers = nLayers;
     if (gvre && gvre->begin_layer)
-       gvre->begin_layer(job, layername);
+       gvre->begin_layer(job, gvc->layerIDs[gvc->layerNum], gvc->layerNum, gvc->numLayers);
 #ifndef DISABLE_CODEGENS
     else {
        codegen_t *cg = job->codegen;
 
        if (cg && cg->begin_layer)
-           cg->begin_layer(layername, layer, nLayers);
+           cg->begin_layer(gvc->layerIDs[gvc->layerNum], gvc->layerNum, gvc->numLayers);
     }
 #endif
 }
@@ -378,8 +381,6 @@ void gvrender_end_layer(GVC_t * gvc)
            cg->end_layer();
     }
 #endif
-    job->layer = 0;
-    job->nLayers = 0;
 }
 
 void gvrender_begin_cluster(GVC_t * gvc, graph_t * sg)
index b7498a28506600f8a6b72e32cb0dc6b24908bf06..885aa6e086a11461922d710b1cd3242ed639efcc 100644 (file)
@@ -443,10 +443,6 @@ void cAdjust(graph_t * g, int xy)
     free(nlist);
 }
 
-typedef struct {
-    pointf LL;
-    pointf UR;
-} boxf;
 typedef struct {
     pointf pos;                        /* position for sorting */
     boxf bb;