else assert(0);
}
+/* makePortLabels:
+ * Add head and tail labels if necessary and update bounding box.
+ */
+void makePortLabels(edge_t * e)
+{
+ if (ED_head_label(e) && !ED_head_label(e)->set) {
+ place_portlabel(e, TRUE);
+ updateBB(agraphof(agtail(e)), ED_head_label(e));
+ }
+ if (ED_tail_label(e) && !ED_tail_label(e)->set) {
+ place_portlabel(e, FALSE);
+ updateBB(agraphof(agtail(e)), ED_tail_label(e));
+ }
+}
+
+/* endPoints:
+ * Extract the actual end points of the spline, where
+ * they touch the node.
+ */
+static void endPoints(splines * spl, pointf * p, pointf * q)
+{
+ bezier bz;
+
+ bz = spl->list[0];
+ if (bz.sflag) {
+ *p = bz.sp;
+ }
+ else {
+ *p = bz.list[0];
+ }
+ bz = spl->list[spl->size - 1];
+ if (bz.eflag) {
+ *q = bz.ep;
+ }
+ else {
+ *q = bz.list[bz.size - 1];
+ }
+}
+
+/* polylineMidpoint;
+ * Find midpoint of polyline.
+ * pp and pq are set to the endpoints of the line segment containing it.
+ */
+static pointf
+polylineMidpoint (splines* spl, pointf* pp, pointf* pq)
+{
+ bezier bz;
+ int i, j, k;
+ double d, dist = 0;
+ pointf pf, qf, mf;
+
+ for (i = 0; i < spl->size; i++) {
+ bz = spl->list[i];
+ for (j = 0, k=3; k < bz.size; j+=3,k+=3) {
+ pf = bz.list[j];
+ qf = bz.list[k];
+ dist += DIST(pf, qf);
+ }
+ }
+ dist /= 2;
+ for (i = 0; i < spl->size; i++) {
+ bz = spl->list[i];
+ for (j = 0, k=3; k < bz.size; j+=3,k+=3) {
+ pf = bz.list[j];
+ qf = bz.list[k];
+ d = DIST(pf,qf);
+ if (d >= dist) {
+ *pp = pf;
+ *pq = qf;
+ mf.x = ((qf.x*dist) + (pf.x*(d-dist)))/d;
+ mf.y = ((qf.y*dist) + (pf.y*(d-dist)))/d;
+ return mf;
+ }
+ else
+ dist -= d;
+ }
+ }
+ assert (FALSE); /* should never get here */
+ return mf;
+}
+
+#define LEFTOF(a,b,c) (((a.y - b.y)*(c.x - b.x) - (c.y - b.y)*(a.x - b.x)) > 0)
+#define MAXLABELWD (POINTS_PER_INCH/2.0)
+
+/* addEdgeLabels:
+ * rp and rq are the port points of the tail and head node.
+ * Adds label, headlabel and taillabel.
+ * The use of 2 and 4 in computing ld.x and ld.y are fudge factors, to
+ * introduce a bit of spacing.
+ * Updates bounding box.
+ * We try to use the actual endpoints of the spline, as they may differ
+ * significantly from rp and rq, but if the spline is degenerate (e.g.,
+ * the nodes overlap), we use rp and rq.
+ */
+void addEdgeLabels(graph_t* g, edge_t * e, pointf rp, pointf rq)
+{
+ int et = EDGE_TYPE (g);
+ pointf p, q;
+ pointf d; /* midpoint of segment p-q */
+ point ld;
+ point del;
+ pointf spf;
+ double f, ht, wd, dist2;
+ int leftOf;
+
+ if (ED_label(e) && !ED_label(e)->set) {
+ endPoints(ED_spl(e), &p, &q);
+ if (APPROXEQPT(p, q, MILLIPOINT)) { /* degenerate spline */
+ p = rp;
+ q = rq;
+ spf = p;
+ }
+ else if (et == ET_SPLINE) {
+ d.x = (q.x + p.x) / 2.;
+ d.y = (p.y + q.y) / 2.;
+ spf = dotneato_closest(ED_spl(e), d);
+ }
+ else { /* ET_PLINE, ET_ORTHO or ET_LINE */
+ spf = polylineMidpoint (ED_spl(e), &p, &q);
+ }
+ del.x = q.x - p.x;
+ del.y = q.y - p.y;
+ dist2 = del.x*del.x + del.y*del.y;
+ ht = (ED_label(e)->dimen.y + 2)/2.0;
+ if (dist2) {
+ wd = (MIN(ED_label(e)->dimen.x + 2, MAXLABELWD))/2.0;
+ leftOf = LEFTOF(p, q, spf);
+ if ((leftOf && (del.y >= 0)) || (!leftOf && (del.y < 0))) {
+ if (del.x*del.y >= 0)
+ ht *= -1;
+ }
+ else {
+ wd *= -1;
+ if (del.x*del.y < 0)
+ ht *= -1;
+ }
+ f = (del.y*wd - del.x*ht)/dist2;
+ ld.x = -f*del.y;
+ ld.y = f*del.x;
+ }
+ else { /* end points the same */
+ ld.x = 0;
+ ld.y = -ht;
+ }
+
+ ED_label(e)->pos.x = spf.x + ld.x;
+ ED_label(e)->pos.y = spf.y + ld.y;
+ ED_label(e)->set = TRUE;
+ updateBB(agraphof(agtail(e)), ED_label(e));
+ }
+ makePortLabels(e);
+}
+
/* vladimir */
void place_portlabel(edge_t * e, boolean head_p)
/* place the {head,tail}label (depending on HEAD_P) of edge E */