#pragma prototyped
#include "render.h"
#include "htmltable.h"
#define REGULAR 0
#define BOLD 1
#define ITALIC 2
#define P_SOLID 0
#define P_NONE 15
#define P_DOTTED 4
#define P_DASHED 11
#define GD_RESOLUTION 96
#define SCALE ((double)GD_RESOLUTION/(double)POINTS_PER_INCH)
#define WIDTH_NORMAL 1
#define WIDTH_BOLD 3
static int onetime = TRUE;
typedef struct context_t {
char color_ix, *fontfam, fontopt, font_was_set;
char pen, fill, penwidth, style_was_set;
double fontsz;
} context_t;
#ifdef OLD
#define MAXNEST 4
static context_t cstk[MAXNEST];
static int SP;
#endif
static int Rot;
static point Viewport;
static pointf GraphFocus;
static double Zoom;
static point mappt(pointf p)
{
point rv;
if (Rot == 0) {
rv.x = (p.x - GraphFocus.x) * Zoom + Viewport.x/2.;
rv.y = (p.y - GraphFocus.y) * -Zoom + Viewport.y/2.;
} else {
rv.x = (p.y - GraphFocus.y) * Zoom + Viewport.x/2.;
rv.y = (p.x - GraphFocus.x) * -Zoom + Viewport.y/2.;
}
if (rv.x < 0) rv.x = 0;
if (rv.x >= Viewport.x) rv.x = Viewport.x - 1;
if (rv.y < 0) rv.y = 0;
if (rv.y >= Viewport.y) rv.y = Viewport.y - 1;
return rv;
}
static void
map_output_rect (pointf p1, pointf p2, char *url, char *target, char *label, char *tooltip)
{
point pp1,pp2;
double t;
if (!(url && url[0])) return;
if (Output_lang == ISMAP
|| Output_lang == IMAP
|| Output_lang == CMAP
|| Output_lang == CMAPX) {
pp1 = mappt(p1);
pp2 = mappt(p2);
} else {
pp1.x = ROUND(p1.x); pp1.y = ROUND(p1.y);
pp2.x = ROUND(p2.x); pp2.y = ROUND(p2.y);
}
if (pp1.x == pp2.x || pp1.y == pp2.y) return;
if (pp2.x < pp1.x) {
t = pp2.x;
pp2.x = pp1.x;
pp1.x = t;
}
if (pp2.y < pp1.y) {
t = pp2.y;
pp2.y = pp1.y;
pp1.y = t;
}
if (Output_lang == IMAP) {
fprintf(Output_file,"rect %s %d,%d %d,%d\n",
url,pp1.x,pp1.y,pp2.x,pp2.y);
} else if (Output_lang == ISMAP) {
fprintf(Output_file,"rectangle (%d,%d) (%d,%d) %s %s\n",
pp1.x,pp1.y,pp2.x,pp2.y,url,label);
} else if (Output_lang == CMAP || Output_lang == CMAPX) {
fprintf(Output_file,"<area shape=\"rect\" href=\"%s\"",
xml_string(url));
if (target && target[0]) {
fprintf(Output_file," target=\"%s\"", xml_string(target));
}
if (tooltip && tooltip[0]) {
fprintf(Output_file," title=\"%s\"", xml_string(tooltip));
}
if (label && label[0]) {
fprintf(Output_file," alt=\"%s\"", xml_string(label));
} else {
fprintf(Output_file," alt=\"\"");
}
fprintf(Output_file," coords=\"%d,%d,%d,%d\"",
pp1.x,pp1.y,pp2.x,pp2.y);
if (Output_lang == CMAPX)
fprintf(Output_file," /");
fprintf(Output_file,">\n");
} else if (Output_lang == POSTSCRIPT || Output_lang == PDF) {
fprintf(Output_file,"[ /Rect [ %d %d %d %d ]\n"
" /Border [ 0 0 0 ]\n"
" /Action << /Subtype /URI /URI %s >>\n"
" /Subtype /Link\n"
"/ANN pdfmark\n",
pp1.x,pp1.y,pp2.x,pp2.y,
ps_string(url));
}
}
#define FUZZ 3
static void
map_output_fuzzy_point (pointf p, char *url, char *target, char *label, char *tooltip)
{
pointf p1, p2;
p1.x = p.x - FUZZ;
p1.y = p.y - FUZZ;
p2.x = p.x + FUZZ;
p2.y = p.y + FUZZ;
map_output_rect(p1, p2, url, target, label, tooltip);
}
static void
map_reset(void)
{
onetime = TRUE;
}
static void
init_imap(void)
{
#ifdef OLD
SP = 0;
cstk[0].color_ix = 0;
cstk[0].fontfam = "Times";
cstk[0].fontopt = REGULAR;
cstk[0].pen = P_SOLID;
cstk[0].fill = P_NONE;
cstk[0].penwidth = WIDTH_NORMAL;
#endif
}
static void
doHTMLdata (htmldata_t* dp, point p, void* obj)
{
char *url;
pointf p1,p2;
if ((url = dp->href) && url[0]) {
switch (agobjkind(obj)) {
case AGGRAPH:
url = strdup_and_subst_graph(url,(graph_t*)obj);
break;
case AGNODE:
url = strdup_and_subst_node(url,(node_t*)obj);
break;
case AGEDGE:
url = strdup_and_subst_edge(url,(edge_t*)obj);
break;
}
p1.x = p.x + dp->box.LL.x;
p1.y = p.y + dp->box.LL.y;
p2.x = p.x + dp->box.UR.x;
p2.y = p.y + dp->box.UR.y;
map_output_rect(p1,p2,url,"","",0);
free(url);
}
}
static void doHTMLtbl (htmltbl_t*, point, void*);
static void
doHTMLcell (htmlcell_t* cp, point p, void* obj)
{
if (cp->child.kind == HTML_TBL)
doHTMLtbl (cp->child.u.tbl, p, obj);
if (cp->data.href)
doHTMLdata (&cp->data, p, obj);
}
static void
doHTMLtbl (htmltbl_t* tbl, point p, void* obj)
{
htmlcell_t** cells = tbl->u.n.cells;
htmlcell_t* cp;
while ((cp = *cells++))
doHTMLcell (cp, p, obj);
if (tbl->data.href)
doHTMLdata (&tbl->data, p, obj);
}
static void
doHTMLlabel (htmllabel_t* lbl, point p, void* obj)
{
if (lbl->kind == HTML_TBL) {
doHTMLtbl (lbl->u.tbl, p, obj);
}
}
static void
map_begin_job(FILE *ofp, graph_t *g, char **lib, char *user, char *info[], point pages)
{
if (Output_lang == IMAP) {
fprintf(Output_file,"base referer\n");
} else if (Output_lang == ISMAP) {
} else if (Output_lang == CMAP || Output_lang == CMAPX) {
} else if (Output_lang == POSTSCRIPT || Output_lang == PDF) {
}
}
static void
map_begin_graph(graph_t* g, box bb, point pb)
{
Viewport = GD_drawing(g)->viewport.size;
if (Viewport.x) {
GraphFocus = GD_drawing(g)->viewport.focus;
Zoom = GD_drawing(g)->viewport.zoom;
}
else {
Viewport.x = (bb.UR.x - bb.LL.x + 2*GD_drawing(g)->margin.x) * SCALE + 1;
Viewport.y = (bb.UR.y - bb.LL.y + 2*GD_drawing(g)->margin.y) * SCALE + 1;
GraphFocus.x = (GD_bb(g).UR.x - GD_bb(g).LL.x) / 2.;
GraphFocus.y = (GD_bb(g).UR.y - GD_bb(g).LL.y) / 2.;
Zoom = SCALE;
}
if (onetime) {
init_imap();
onetime = FALSE;
}
}
static graph_t* Root_Graph;
static char *Default_URL;
static void
map_begin_page(graph_t *g, point page, double scale, int rot, point offset)
{
char *url;
Zoom *= scale;
Rot = rot;
if (Output_lang == CMAPX) {
fprintf(Output_file,"<map id=\"%s\" name=\"%s\">\n",g->name,g->name);
}
Root_Graph = g;
Default_URL = NULL;
if (((url = agget(g, "href")) && url[0])
|| ((url = agget(g, "URL")) && url[0])) {
if (Output_lang == IMAP) {
fprintf(Output_file,"default %s\n",url);
} else if (Output_lang == ISMAP) {
fprintf(Output_file,"default %s %s\n",url,g->name);
} else if (Output_lang == CMAP || Output_lang == CMAPX) {
Default_URL = url;
}
}
}
static void map_end_page(void) {
pointf Default_p1,Default_p2;
char *Default_label;
graph_t* g = Root_Graph;
if (GD_label(g) && GD_label(g)->html)
doHTMLlabel (GD_label(g)->u.html, GD_label(g)->p, (void*)g);
if (Default_URL) {
Default_URL = strdup_and_subst_graph(Default_URL,g);
Default_label = g->name;
Default_p1.x = GD_bb(g).LL.x;
Default_p1.y = GD_bb(g).LL.y;
Default_p2.x = GD_bb(g).UR.x;
Default_p2.y = GD_bb(g).UR.y;
map_output_rect(Default_p1,Default_p2,Default_URL,"",Default_label,"");
free(Default_URL);
}
if (Output_lang == CMAPX) {
fprintf(Output_file,"</map>\n");
}
}
void
map_begin_cluster(graph_t* g)
{
char *url, *target, *title="", *m_target=NULL;
pointf p1,p2;
if (GD_label(g) && GD_label(g)->html)
doHTMLlabel (GD_label(g)->u.html, GD_label(g)->p, (void*)g);
if (((url = agget(g, "href")) && url[0])
|| ((url = agget(g, "URL")) && url[0])) {
if (GD_label(g) != NULL)
title=GD_label(g)->text;
if ((target = agget(g, "target")) && target[0]) {
m_target = target = strdup_and_subst_graph(target,g);
}
p1.x = GD_bb(g).LL.x;
p1.y = GD_bb(g).LL.y;
p2.x = GD_bb(g).UR.x;
p2.y = GD_bb(g).UR.y;
url = strdup_and_subst_graph(url,g);
map_output_rect(p1,p2,url,target,title,title);
if (m_target)
free(m_target);
free(url);
}
}
void
map_begin_node(node_t* n)
{
char *url, *target, *tooltip, *m_target=NULL, *m_tooltip=NULL;
pointf p1,p2;
if (ND_label(n)->html)
doHTMLlabel (ND_label(n)->u.html, ND_coord_i(n), (void*)n);
if (((url = agget(n, "href")) && url[0])
|| ((url = agget(n, "URL")) && url[0])) {
if ((target = agget(n, "target")) && target[0]) {
m_target = target = strdup_and_subst_node(target,n);
}
p1.x = ND_coord_i(n).x - ND_lw_i(n);
p1.y = ND_coord_i(n).y - (ND_ht_i(n)/2);
p2.x = ND_coord_i(n).x + ND_rw_i(n);
p2.y = ND_coord_i(n).y + (ND_ht_i(n)/2);
url = strdup_and_subst_node(url,n);
if ((tooltip = agget(n, "tooltip")) && tooltip[0]) {
m_tooltip = tooltip = strdup_and_subst_node(tooltip,n);
}
else {
tooltip = ND_label(n)->text;
}
map_output_rect(p1,p2,url,target,ND_label(n)->text,tooltip);
if (m_target)
free(m_target);
if (m_tooltip)
free(m_tooltip);
free(url);
}
}
void
map_begin_edge(edge_t* e)
{
char *label, *taillabel, *headlabel;
char *url, *headurl, *tailurl, *tooltip, *target;
char *tailtooltip=NULL, *headtooltip=NULL, *tailtarget=NULL, *headtarget=NULL;
char *m_url=NULL, *m_headurl=NULL, *m_tailurl=NULL;
char *m_target=NULL, *m_tailtarget=NULL, *m_headtarget=NULL;
char *m_tooltip=NULL, *m_tailtooltip=NULL, *m_headtooltip=NULL;
textlabel_t *lab=NULL, *tlab=NULL, *hlab=NULL;
pointf p,p1,p2;
bezier bz;
if ((lab=ED_label(e))) {
if (lab->html)
doHTMLlabel (lab->u.html, lab->p, (void*)e);
label = lab->text;
} else {
label = "";
}
if (((url = agget(e, "href")) && url[0])
|| ((url = agget(e, "URL")) && url[0])) {
m_url = url = strdup_and_subst_edge(url,e);
if ((tooltip = agget(e, "tooltip")) && tooltip[0]) {
m_tooltip = tooltip = strdup_and_subst_edge(tooltip,e);
} else {
tooltip = label;
}
if ((target = agget(e, "target")) && target[0]) {
m_target = target = strdup_and_subst_edge(target,e);
} else {
target = "";
}
} else {
tooltip = "";
target = "";
}
if ((tlab=ED_tail_label(e))) {
if (tlab->html)
doHTMLlabel (tlab->u.html, tlab->p, (void*)e);
taillabel = tlab->text;
} else {
taillabel=label;
}
if (((tailurl = agget(e, "tailhref")) && tailurl[0])
|| ((tailurl = agget(e, "tailURL")) && tailurl[0])) {
m_tailurl = tailurl = strdup_and_subst_edge(tailurl,e);
if ((tailtooltip = agget(e, "tailtooltip")) && tailtooltip[0]) {
m_tailtooltip = tailtooltip = strdup_and_subst_edge(tailtooltip,e);
} else {
tailtooltip = taillabel;
}
if ((tailtarget = agget(e, "tailtarget")) && tailtarget[0]) {
m_tailtarget = tailtarget = strdup_and_subst_edge(tailtarget,e);
} else {
tailtarget = target;
}
} else if (url) {
tailurl = url;
tailtooltip = tooltip;
tailtarget = target;
}
if ((hlab=ED_head_label(e))) {
if (hlab->html)
doHTMLlabel (hlab->u.html, hlab->p, (void*)e);
headlabel = hlab->text;
} else {
headlabel = label;
}
if (((headurl = agget(e, "headhref")) && headurl[0])
|| ((headurl = agget(e, "headURL")) && headurl[0])) {
m_headurl = headurl = strdup_and_subst_edge(headurl,e);
if ((headtooltip = agget(e, "headtooltip")) && headtooltip[0]) {
m_headtooltip = headtooltip = strdup_and_subst_edge(headtooltip,e);
} else {
headtooltip = headlabel;
}
if ((headtarget = agget(e, "headtarget")) && headtarget[0]) {
m_headtarget = headtarget = strdup_and_subst_edge(headtarget,e);
} else {
headtarget = target;
}
} else if (url) {
headurl = url;
headtooltip = tooltip;
headtarget = target;
}
if (lab && url) {
p1.x = lab->p.x - lab->dimen.x*64/2;
p1.y = lab->p.y - lab->dimen.y*64/2;
p2.x = lab->p.x + lab->dimen.x*64/2;
p2.y = lab->p.y + lab->dimen.y*64/2;
map_output_rect(p1,p2,url,target,label,tooltip);
}
if (tlab && (url || tailurl)) {
p1.x = tlab->p.x - tlab->dimen.x*64/2;
p1.y = tlab->p.y - tlab->dimen.y*64/2;
p2.x = tlab->p.x + tlab->dimen.x*64/2;
p2.y = tlab->p.y + tlab->dimen.y*64/2;
map_output_rect(p1,p2,tailurl,tailtarget,taillabel,tailtooltip);
}
if (hlab && (url || headurl)) {
p1.x = hlab->p.x - hlab->dimen.x*64/2;
p1.y = hlab->p.y - hlab->dimen.y*64/2;
p2.x = hlab->p.x + hlab->dimen.x*64/2;
p2.y = hlab->p.y + hlab->dimen.y*64/2;
map_output_rect(p1,p2,headurl,headtarget,headlabel,headtooltip);
}
#if 0
# FIXME - what is this supposed to do? Perhaps map spline control points?
if (ED_spl(e) && url) {
int i,j;
for (i = 0; i < ED_spl(e)->size; i++) {
bz = ED_spl(e)->list[i];
for (j = 0; j < bz.size; j +=3) {
if (((i == 0) && (j == 0))
|| ((i == (ED_spl(e)->size -1)) && (j == (bz.size - 1)))) {
continue;
}
p.x = bz.list[j].x;
p.y = bz.list[j].y;
map_output_fuzzy_point(p, url, ED_label(e)->text);
}
}
}
#endif
if (ED_spl(e) && (url || tailurl)) {
bz = ED_spl(e)->list[0];
if (bz.sflag) {
p.x = bz.sp.x;
p.y = bz.sp.y;
} else {
p.x = bz.list[0].x;
p.y = bz.list[0].y;
}
map_output_fuzzy_point(p, tailurl, tailtarget, taillabel, tailtooltip);
}
if (ED_spl(e) && (url || headurl)) {
bz = ED_spl(e)->list[ED_spl(e)->size-1];
if (bz.eflag) {
p.x = bz.ep.x;
p.y = bz.ep.y;
} else {
p.x = bz.list[bz.size-1].x;
p.y = bz.list[bz.size-1].y;
}
map_output_fuzzy_point(p, headurl, headtarget, headlabel, headtooltip);
}
if (m_url) free(m_url);
if (m_target) free(m_target);
if (m_tailtarget) free(m_tailtarget);
if (m_headtarget) free(m_headtarget);
if (m_tailurl) free(m_tailurl);
if (m_headurl) free(m_headurl);
if (m_tooltip) free(m_tooltip);
if (m_tailtooltip) free(m_tailtooltip);
if (m_headtooltip) free(m_headtooltip);
}
codegen_t IMAP_CodeGen = {
map_reset,
map_begin_job, 0,
map_begin_graph, 0,
map_begin_page, map_end_page,
0, 0,
map_begin_cluster, 0,
0, 0,
0, 0,
map_begin_node, 0,
map_begin_edge, 0,
0, 0,
0, 0,
0, 0, 0,
0, 0,
0, 0,
0,
0,
gd_textsize,
0,
0
};
codegen_t ISMAP_CodeGen = {
map_reset,
map_begin_job, 0,
map_begin_graph, 0,
map_begin_page, map_end_page,
0, 0,
map_begin_cluster, 0,
0, 0,
0, 0,
map_begin_node, 0,
map_begin_edge, 0,
0, 0,
0, 0,
0, 0, 0,
0, 0,
0, 0,
0,
0,
gd_textsize,
0,
0
};
codegen_t CMAP_CodeGen = {
map_reset,
map_begin_job, 0,
map_begin_graph, 0,
map_begin_page, map_end_page,
0, 0,
map_begin_cluster, 0,
0, 0,
0, 0,
map_begin_node, 0,
map_begin_edge, 0,
0, 0,
0, 0,
0, 0, 0,
0, 0,
0, 0,
0,
0,
gd_textsize,
0,
0
};
codegen_t CMAPX_CodeGen = {
map_reset,
map_begin_job, 0,
map_begin_graph, 0,
map_begin_page, map_end_page,
0, 0,
map_begin_cluster, 0,
0, 0,
0, 0,
map_begin_node, 0,
map_begin_edge, 0,
0, 0,
0, 0,
0, 0, 0,
0, 0,
0, 0,
0,
0,
gd_textsize,
0,
0
};