Current File : //usr/share/graphviz/lefty/dotty.lefty
#
# DOTTY
#
dotty = [
    'keys' = [
        'nid'    = 'nid';
        'eid'    = 'eid';
        'gid'    = 'gid';
        'name'   = 'name';
        'attr'   = 'attr';
        'gattr'  = 'graphattr';
        'eattr'  = 'edgeattr';
        'nattr'  = 'nodeattr';
        'edges'  = 'edges';
        'tail'   = 'tail';
        'tport'  = 'tport';
        'head'   = 'head';
        'hport'  = 'hport';
        'pos'    = 'pos';
        'size'   = 'size';
        'rect'   = 'rect';
        'fname'  = 'fontname';
        'fsize'  = 'fontsize';
        'fcolor' = 'fontcolor';
        'dcolor' = 'drawcolor';
        'bcolor' = 'fillcolor';
    ];
    'maps' = [
        'X11' = [
            'fontmap' = [
                'Times-Roman'    = '-*-times-medium-r-*--%d-*-*-*-*-*-*-1';
                'Times-Italic'   = '-*-times-medium-i-*--%d-*-*-*-*-*-*-1';
                'Times-Bold'     = '-*-times-bold-r-*--%d-*-*-*-*-*-*-1';
                'Courier'        = '-*-courier-bold-r-*--%d-*-*-*-*-*-*-1';
                'Courier-Bold'   = '-*-courier-bold-r-*--%d-*-*-*-*-*-*-1';
                'Helvetica'      = (
                     '-*-helvetica-medium-r-normal--%d-*-*-*-p-*-iso8859-1'
                );
                'Helvetica-Bold' = (
                    '-*-helvetica-bold-r-normal--%d-*-*-*-p-*-iso8859-1'
                );
            ];
            'psfontmap' = [
                'Times-Roman'    = 'Times-Roman';
                'Times-Italic'   = 'Times-Italic';
                'Times-Bold'     = 'Times-Bold';
                'Courier'        = 'Courier';
                'Courier-Bold'   = 'Courier-Bold';
                'Helvetica'      = 'Helvetica';
                'Helvetica-Bold' = 'Helvetica-Bold';
            ];
        ];
        'mswin' = [
            'fontmap' = [
                'Times-Roman'    = 'Times New Roman';
                'Times-Italic'   = 'Times New Roman Italic';
                'Times-Bold'     = 'Times New Roman Bold';
                'Courier'        = 'Courier New';
                'Courier-Bold'   = 'Courier New Bold';
                'Helvetica'      = 'Arial';
                'Helvetica-Bold' = 'Arial Bold';
            ];
            'psfontmap' = [
                'Times-Roman'    = 'Times New Roman';
                'Times-Italic'   = 'Times New Roman Italic';
                'Times-Bold'     = 'Times New Roman Bold';
                'Courier'        = 'Courier New';
                'Courier-Bold'   = 'Courier New Bold';
                'Helvetica'      = 'Arial';
                'Helvetica-Bold' = 'Arial Bold';
            ];
        ];
    ];
    'protogt' = [
        'graph' = [
            'graphattr' = [
                'fontsize' = '14';
                'fontname' = 'Times-Roman';
                'fontcolor' = 'black';
            ];
            'nodeattr' = [
                'shape' = 'ellipse';
                'fontsize' = '14';
                'fontname' = 'Times-Roman';
                'fontcolor' = 'black';
                'style' = 'solid';
            ];
            'edgeattr' = [
                'fontsize' = '14';
                'fontname' = 'Times-Roman';
                'fontcolor' = 'black';
                'style' = 'solid';
            ];
            'graphdict' = [];
            'nodedict' = [];
            'graphs' = [];
            'nodes' = [];
            'edges' = [];
            'maxgid' = 0;
            'maxnid' = 0;
            'maxeid' = 0;
            'type' = 'digraph';
        ];
        'layoutmode' = 'sync';
        'lserver' = 'dot';
        'edgehandles' = 1;
        'noundo' = 0;
    ];
    'lservers' = [];
    'mlevel' = 0;
    'graphs' = [];
    'views' = [];
    'protovt' = [
        'normal' = [
            'name' = 'DOTTY';
            'orig' = ['x' = 1; 'y' = 1;];
            'size' = ['x' = 420; 'y' = 520;];
            'wrect' = [
                0 = ['x' = 0; 'y' = 0;];
                1 = ['x' = 400; 'y' = 500;];
            ];
            'vsize' = ['x' = 400; 'y' = 500;];
            'w2v' = 1;
        ];
        'birdseye' = [
            'type' = 'birdseye';
            'name' = 'DOTTY birdseye view';
            'orig' = ['x' = 1; 'y' = 1;];
            'size' = ['x' = 220; 'y' = 260;];
            'wrect' = [
                0 = ['x' = 0; 'y' = 0;];
                1 = ['x' = 200; 'y' = 250;];
            ];
            'vsize' = ['x' = 200; 'y' = 250;];
            'w2v' = 1;
        ];
    ];
    'pagesizes' = [
        '8.5x11' = ['x' =    8; 'y' = 10.5;];
        '11x17'  = ['x' = 10.5; 'y' = 16.5;];
        '36x50'  = ['x' = 35.5; 'y' = 49.5;];
    ];
];
load ('dotty_draw.lefty');
load ('dotty_edit.lefty');
load ('dotty_layout.lefty');
load ('dotty_ui.lefty');
#
# initialization functions
#
dotty.init = function () {
    dotty.fontmap = dotty.maps[getenv ('LEFTYWINSYS')].fontmap;
    dotty.clipgt = dotty.protogt.creategraph (['noundo' = 1;]);
    dotty.inited = 1;
};
dotty.simple = function (file) {
    if (dotty.inited ~= 1)
        dotty.init ();
    dotty.createviewandgraph (file, 'file', null, null);
    txtview ('off');
};
#
# main operations
#
dotty.protogt.creategraph = function (protogt) {
    local gt, id, gtid;

    if (~protogt)
        protogt = dotty.protogt;
    for (gtid = 0; dotty.graphs[gtid]; gtid = gtid + 1)
        ;
    gt = (dotty.graphs[gtid] = []);
    if (protogt.mode ~= 'replace') {
        for (id in dotty.protogt)
            gt[id] = copy (dotty.protogt[id]);
    }
    for (id in protogt)
        gt[id] = copy (protogt[id]);
    gt.gtid = gtid;
    gt.views = [];
    gt.undoarray = ['level' = 0; 'entries' = [];];
    gt.busy = 0;
    return gt;
};
dotty.protogt.copygraph = function (ogt) {
    local gt, gtid, id;

    for (gtid = 0; dotty.graphs[gtid]; gtid = gtid + 1)
        ;
    gt = (dotty.graphs[gtid] = []);
    for (id in ogt)
        gt[id] = copy (ogt[id]);
    gt.gtid = gtid;
    gt.views = [];
    gt.undoarray = ['level' = 0; 'entries' = [];];
    gt.busy = 0;
    return gt;
};
dotty.protogt.destroygraph = function (gt) {
    local vid, vlist;

    if (gt.layoutpending > 0)
        gt.cancellayout (gt);
    for (vid in gt.views)
        vlist[vid] = gt.views[vid];
    for (vid in gt.views)
        gt.destroyview (gt, vlist[vid]);
    remove (gt.gtid, dotty.graphs);
};
dotty.protogt.loadgraph = function (gt, name, type, protograph, layoutflag) {
    local fd, vid, vt, graph, nid, eid, gid;

    if (gt.layoutpending > 0)
        gt.cancellayout (gt);
    if (~name)
        if (~(name = ask ('file name:', 'file', '')))
            return;
    dotty.pushbusy (gt, gt.views);
    dotty.message (1, 'loading');
    if (~protograph)
        protograph = dotty.protogt.graph;
    if (
        ~((fd = dotty.openio (name, type, 'r')) >= 0) |
        ~(graph = readgraph (fd, protograph))
    ) {
        dotty.message (0, 'cannot load graph');
        dotty.popbusy (gt, gt.views);
        return;
    }
    for (vid in gt.views) {
        vt = gt.views[vid];
        vt.colors = [];
        vt.colorn = 2;
    }
    gt.graph = graph;
    gt.name = name;
    gt.type = type;
    gt.undoarray = ['level' = 0; 'entries' = [];];
    if (~(type == 'file' & name == '-'))
        closeio (fd);
    graph.maxgid = tablesize (graph.graphs);
    graph.maxnid = tablesize (graph.nodes);
    graph.maxeid = tablesize (graph.edges);
    for (nid in graph.nodes)
        graph.nodes[nid][dotty.keys.nid] = nid;
    for (eid in graph.edges)
        graph.edges[eid][dotty.keys.eid] = eid;
    for (gid in graph.graphs)
        graph.graphs[gid][dotty.keys.gid] = gid;
    gt.unpackattr (gt);
    if (layoutflag) {
        dotty.message (1, 'generating layout');
        gt.layoutgraph (gt);
    }
    dotty.popbusy (gt, gt.views);
    return gt.graph;
};
dotty.protogt.savegraph = function (gt, name, type) {
    local fd;

    if (~name)
        if (~(name = ask ('file name:', 'file', '')))
            return;
    if (
        ~((fd = dotty.openio (name, type, 'w')) >= 0) |
        ~writegraph (fd, gt.graph, 0)
    ) {
        dotty.message (0, 'cannot save graph');
        return;
    }
    if (~(type == 'file' & name == '-'))
        closeio (fd);
};
dotty.protogt.setgraph = function (gt, graph) {
    local vid, vt, nid, eid, gid;

    if (gt.layoutpending > 0)
        gt.cancellayout (gt);
    for (vid in gt.views) {
        vt = gt.views[vid];
        vt.colors = [];
        vt.colorn = 2;
    }
    gt.graph = copy (graph);
    gt.undoarray = ['level' = 0; 'entries' = [];];
    gt.unpackattr (gt);
    gt.graph.maxgid = tablesize (graph.graphs);
    gt.graph.maxnid = tablesize (graph.nodes);
    gt.graph.maxeid = tablesize (graph.edges);
    for (nid in gt.graph.nodes)
        gt.graph.nodes[nid][dotty.keys.nid] = nid;
    for (eid in gt.graph.edges)
        gt.graph.edges[eid][dotty.keys.eid] = eid;
    for (gid in gt.graph.graphs)
        gt.graph.graphs[gid][dotty.keys.gid] = gid;
    gt.unpackattr (gt);
    dotty.message (1, 'generating layout');
    gt.layoutgraph (gt);
    return gt.graph;
};
dotty.protogt.erasegraph = function (gt, protogt, protovt) {
    local vid, vt;

    if (gt.layoutpending > 0)
        gt.cancellayout (gt);
    for (vid in gt.views) {
        vt = gt.views[vid];
        vt.colors = [];
        vt.colorn = 2;
        clear (vt.canvas);
    }
    if (~protogt)
        protogt = dotty.protogt;
    gt.graph = copy (protogt.graph);
    gt.undoarray = ['level' = 0; 'entries' = [];];
};
dotty.protogt.layoutgraph = function (gt) {
    if (gt.graph.graphattr.xdotversion) {
        gt.unpacklayout (gt, gt.graph);
        gt.setviewsize (gt.views, gt.graph.rect);
        gt.redrawgraph (gt, gt.views);
        return;
    }
    if (gt.layoutmode == 'async') {
        if (~gt.haveinput) {
            gt.startlayout (gt);
            return;
        }
        if (~gt.finishlayout (gt))
            return;
        gt.setviewsize (gt.views, gt.graph.rect);
        gt.redrawgraph (gt, gt.views);
    } else {
        if (~gt.startlayout (gt))
            return;
        else
            while (~gt.finishlayout (gt))
                ;
        gt.setviewsize (gt.views, gt.graph.rect);
        gt.redrawgraph (gt, gt.views);
    }
};
dotty.protogt.createview = function (gt, protovt) {
    local vt, ovt, id, t;

    vt = [];
    vt.colors = [];
    vt.colorn = 2;
    if (~protovt)
        protovt = dotty.protovt.normal;
    if (protovt.mode ~= 'replace') {
        for (id in dotty.protovt[protovt.type])
            vt[id] = copy (dotty.protovt[protovt.type][id]);
    }
    for (id in protovt)
        vt[id] = copy (protovt[id]);
    if (~(vt.parent >= 0)) {
        vt.view = createwidget (-1, [
            'type'   = 'view';
            'name'   = vt.name;
            'origin' = vt.orig;
            'size'   = vt.size;
        ]);
        vt.scroll = createwidget (vt.view, ['type' = 'scroll';]);
    } else {
        vt.view = -1;
        vt.scroll = createwidget (vt.parent, [
            'type' = 'scroll';
            'size' = vt.size;
        ]);
    }
    vt.canvas = createwidget (vt.scroll, [
        'type' = 'canvas';
        'color' = [0 = protovt.bgcolor; 1 = protovt.fgcolor;];
    ]);
    setwidgetattr (vt.canvas, [
        'window' = vt.wrect;
        'viewport' = vt.vsize;
    ]);
    clear (vt.canvas);
    dotty.views[vt.canvas] = vt;
    vt.vtid = vt.canvas;
    vt.gtid = gt.gtid;
    gt.views[vt.vtid] = vt;
    dotty.views[vt.scroll] = vt;
    if (vt.view ~= -1)
        dotty.views[vt.view] = vt;
    if (protovt.colors & tablesize (protovt.colors) > 0) {
        for (id in protovt.colors)
            if (id == '_bgcolor_')
                setwidgetattr (vt.canvas, [
                    'color' = [0 = protovt.colors[id];];
                ]);
            else if (setwidgetattr (vt.canvas, ['color' = [
                protovt.colors[id] = id;
            ];]) ~= 1) {
                t = split (id, ' ');
                if (tablesize (t) ~= 3 | setwidgetattr (vt.canvas, [
                    'color' = [protovt.colors[id] = [
                        'h' = ston (t[0]); 's' = ston (t[1]); 'v' = ston (t[2]);
                    ];];
                ]) ~= 1) {
                    dotty.message (
                        0, concat ('unknown color ', id, ' using #1')
                    );
                }
            }
        vt.colors = copy (protovt.colors);
        vt.colorn = protovt.colorn;
    } else if (tablesize (gt.views) > 1) {
        for (id in gt.views)
            if (gt.views[id] ~= vt)
                break;
        ovt = gt.views[id];
        for (id in ovt.colors)
            if (id == '_bgcolor_')
                setwidgetattr (vt.canvas, ['color' = [0 = ovt.colors[id];];]);
            else if (setwidgetattr (vt.canvas, ['color' = [
                ovt.colors[id] = id;
            ];]) ~= 1) {
                t = split (id, ' ');
                if (tablesize (t) ~= 3 | setwidgetattr (vt.canvas, [
                    'color' = [ovt.colors[id] = [
                        'h' = ston (t[0]); 's' = ston (t[1]); 'v' = ston (t[2]);
                    ];];
                ]) ~= 1) {
                    dotty.message (
                        0, concat ('unknown color ', id, ' using #1')
                    );
                }
            }
        vt.colors = copy (ovt.colors);
        vt.colorn = ovt.colorn;
    }
    if (gt.graph.rect)
        gt.setviewsize ([vt.vtid = vt;], gt.graph.rect);
    gt.drawgraph (gt, [vt.vtid = vt;]);
    for (id in vt.uifuncs)
        if (id == 'closeview')
            widgets[vt.view][id] = vt.uifuncs[id];
        else
            widgets[vt.canvas][id] = vt.uifuncs[id];
    return vt;
};
dotty.protogt.destroyview = function (gt, vt) {
    destroywidget (vt.canvas);
    destroywidget (vt.scroll);
    if (vt.view ~= -1) {
        destroywidget (vt.view);
        remove (vt.view, dotty.views);
    }
    remove (vt.scroll, dotty.views);
    remove (vt.canvas, dotty.views);
    if (vt.gtid >= 0)
        remove (vt.vtid, gt.views);
    if (tablesize (dotty.views) == 0)
        exit ();
};
dotty.protogt.zoom = function (gt, vt, factor, pos) {
    gt.setviewscale ([vt.vtid = vt;], factor);
    if (pos)
        gt.setviewcenter ([vt.vtid = vt;], pos);
    gt.redrawgraph (gt, [vt.vtid = vt;]);
};
dotty.protogt.findnode = function (gt, vt) {
    local key, node, node1, nid;

    if (~(key = ask ('give node name or label')))
        return;
    if (gt.graph.nodedict[key] >= 0)
        node = gt.graph.nodes[gt.graph.nodedict[key]];
    else if (gt.graph.nodedict[ston (key)] >= 0)
        node = gt.graph.nodes[gt.graph.nodedict[ston (key)]];
    else {
        for (nid in gt.graph.nodes) {
            node1 = gt.graph.nodes[nid];
            if (node1.attr.label == key | node1.attr.label == ston (key)) {
                node = node1;
                break;
            }
        }
    }
    if (~node) {
        dotty.message (0, concat ('cannot find node: ', key));
        return;
    }
    gt.setviewcenter ([vt.vtid = vt;], node.pos);
};
dotty.protogt.setattr = function (gt, obj) {
    local kv, t, attr, value, n, i, s;

    if (~(kv = ask ('give attr/value, eg. color=blue')))
        return;
    t = split (kv, '=');
    attr = t[0];
    value = t[1];
    if ((n = tablesize (t)) > 2)
        for (i = 2; i < n; i = i + 1)
            value = concat (value, '=', t[i]);
    # Check for HTML string and convert using lefty convention
    s = split (value, '');
    n = tablesize (s);
    if ((s[0] == '<') & (s[n-1] == '>')) {
        s[0] = '>';
        s[n-1] = '<';
        value = s[0]; 
        for (i = 1; i < n; i = i + 1)
            value = concat (value, s[i]);
    }
    if (
        obj.attr == gt.graph.graphattr |
        obj.attr == gt.graph.edgeattr |
        obj.attr == gt.graph.nodeattr
    ) {
        obj.attr[attr] = value;
        return;
    }
    if (obj.nid >= 0) {
        gt.undrawnode (gt, gt.views, obj);
        obj.attr[attr] = value;
        gt.unpacknodeattr (gt, obj);
        gt.drawnode (gt, gt.views, obj);
    } else if (obj.eid >= 0) {
        gt.undrawedge (gt, gt.views, obj);
        obj.attr[attr] = value;
        gt.unpackedgeattr (gt, obj);
        gt.drawedge (gt, gt.views, obj);
    }
};
dotty.protogt.getattr = function (gt, node) {
    local kv;

    if (~(kv.key = ask ('give attr name')))
        return null;
    if ((kv.val = node.attr[kv.key]))
        return kv;
    return null;
};
#
# utilities
#
dotty.createviewandgraph = function (name, type, protogt, protovt) {
    local vt, gt;

    if (~protogt)
        protogt = dotty.protogt;
    if (protogt.creategraph)
        gt = protogt.creategraph (protogt);
    else
        gt = dotty.protogt.creategraph (protogt);
    vt = gt.createview (gt, protovt);
    if (~protogt.graph)
        protogt.graph = copy (dotty.protogt.graph);
    if (name)
        gt.loadgraph (gt, name, type, protogt.graph, 1);
    return ['gt' = gt; 'vt' = vt;];
};
dotty.openio = function (name, type, mode) {
    local fd;

    if (~name)
        return null;
    if (type == 'file') {
        if (name == '-') {
            if (mode == 'r' | mode == 'r+')
                fd = 0;
            else
                fd = 1;
        } else if (~((fd = openio ('file', name, mode)) >= 0)) {
            dotty.message (0, concat ('cannot open file: ', name));
            return null;
        }
    } else if (type == 'pipe') {
        if (~((fd = openio (
            'pipe', 'ksh', mode, concat ("%e ", name)
        )) >= 0)) {
            dotty.message (0, concat ('cannot run command: ', name));
            return null;
        }
    } else
        return null;
    return fd;
};
dotty.pushbusy = function (gt, views) {
    local vid;

    if (gt.busy == 0)
        for (vid in gt.views)
            setwidgetattr (vid, ['cursor' = 'watch';]);
    gt.busy = gt.busy + 1;
};
dotty.popbusy = function (gt, views) {
    local vid;

    gt.busy = gt.busy - 1;
    if (gt.busy == 0)
        for (vid in gt.views)
            setwidgetattr (vid, ['cursor' = 'default';]);
};
dotty.message = function (level, text) {
    if (level <= dotty.mlevel)
        echo ('dotty.lefty: ', text);
};
#
# printing or saving to file
#
dotty.protogt.printorsave = function (gt, vt, otype, name, mode, ptype) {
    local pr, wrect, vsize, xy, psize, canvas, pscanvas, cid, cname, t;
    local graph, edgehandles, fontmap, eid, edge, nid, node, gid, sgraph;
    local did, draw, i;

    if (~otype)
        if (~(otype = ask ('print to', 'choice', 'file|printer')))
            return;
    if (otype == 'printer') {
        if (~getenv ('TMPDIR'))
            name = concat (getenv ('HOME'), '/.dottyout.ps');
        else
            name = concat (getenv ('TMPDIR'), '/.dottyout.ps', random (10000));
        if (getenv ('LEFTYWINSYS') ~= 'mswin' & ~pr)
            if (~(pr = ask ('printer command', 'string', 'lpr')))
                return;
    }
    if (~name)
        if (~(name = ask ('postscript file', 'file', 'out.ps')))
            return;
    if (~ptype)
        if (~(ptype = ask ('page size', 'choice', '8.5x11|11x17|36x50')))
            return;
    if (~mode)
        if (~(mode = ask ('mode', 'choice', 'portrait|landscape|best fit')))
            return;
    wrect = copy (vt.wrect);
    wrect[0].x = wrect[0].x - 1;
    wrect[1].x = wrect[1].x + 1;
    wrect[0].y = wrect[0].y - 1;
    wrect[1].y = wrect[1].y + 1;
    vsize = copy (vt.vsize);
    if (vsize.x == 0)
        vsize.x = 1;
    if (vsize.y == 0)
        vsize.y = 1;
    xy = vsize.x / vsize.y;
    if (mode == 'best fit') {
        if (xy < 1)
            mode = 'portrait';
        else
            mode = 'landscape';
    }
    psize = dotty.pagesizes[ptype];
    if (mode == 'portrait') {
        if (xy < psize.x / psize.y) {
            vsize.y = psize.y * 300;
            vsize.x = vsize.y * xy;
        } else {
            vsize.x = psize.x * 300;
            vsize.y = vsize.x / xy;
        }
    } else {
        if (xy < psize.y / psize.x) {
            vsize.y = psize.x * 300;
            vsize.x = vsize.y * xy;
        } else {
            vsize.x = psize.y * 300;
            vsize.y = vsize.x / xy;
        }
    }
    if (~((pscanvas = createwidget (-1, [
        'type'   = 'ps';
        'origin' = ['x' = 0; 'y' = 0;];
        'size'   = vsize;
        'mode'   = mode;
        'name'   = name;
    ])) >= 0)) {
        dotty.message (0, 'cannot open printer device');
        return;
    }
    for (cname in vt.colors) {
        cid = vt.colors[cname];
        if (cname == '_bgcolor_')
            setwidgetattr (pscanvas, ['color' = [0 = cid;];]);
        else if (setwidgetattr (pscanvas, ['color' = [cid = cname;];]) ~= 1) {
            t = split (cname, ' ');
            if (tablesize (t) ~= 3 | setwidgetattr (pscanvas, [
                'color' = [cid = [
                    'h' = ston (t[0]); 's' = ston (t[1]); 'v' = ston (t[2]);
                ];];
            ]) ~= 1) {
                dotty.message (
                    0, concat ('unknown color ', cname, ' using #1')
                );
            }
        }
    }
    setwidgetattr (pscanvas, ['window' = wrect;]);
    graph = copy (gt.graph);
    canvas = vt.canvas;
    vt.canvas = pscanvas;
    edgehandles = gt.edgehandles;
    gt.edgehandles = 0;
    fontmap = dotty.maps[getenv ('LEFTYWINSYS')].psfontmap;
    for (eid in graph.edges) {
        edge = graph.edges[eid];
        edge.fontname = fontmap[edge.attr.fontname];
        for (did in edge.draws) {
            if (did == 'ep')
                continue;
            draw = edge.draws[did];
            for (i = 0; draw[i]; i = i + 1)
                if (draw[i].type == 'F')
                    draw[i].fn = fontmap[draw[i].ofn];
        }
        gt.drawedge (gt, [0 = vt;], edge);
    }
    for (nid in graph.nodes) {
        node = graph.nodes[nid];
        node.fontname = fontmap[node.attr.fontname];
        for (did in node.draws) {
            if (did == 'ep')
                continue;
            draw = node.draws[did];
            for (i = 0; draw[i]; i = i + 1)
                if (draw[i].type == 'F')
                    draw[i].fn = fontmap[draw[i].ofn];
        }
        gt.drawnode (gt, [0 = vt;], node);
    }
    for (gid in graph.graphs) {
        sgraph = graph.graphs[gid];
        sgraph.fontname = fontmap[sgraph.graphattr.fontname];
        for (did in sgraph.draws) {
            if (did == 'ep')
                continue;
            draw = sgraph.draws[did];
            for (i = 0; draw[i]; i = i + 1)
                if (draw[i].type == 'F')
                    draw[i].fn = fontmap[draw[i].ofn];
        }
        gt.drawsgraph (gt, [0 = vt;], sgraph);
    }
    graph.fontname = fontmap[graph.graphattr.fontname];
    gt.drawsgraph (gt, [0 = vt;], graph);
    gt.edgehandles = edgehandles;
    vt.canvas = canvas;
    destroywidget (pscanvas);
    if (otype == 'printer' & getenv ('LEFTYWINSYS') ~= 'mswin')
        system (concat (pr, ' ', name, '; rm ',name));
};
No se encontró la página – Alquiler de Limusinas, Autos Clásicos y Microbuses

Alquiler de Autos Clásicos para Sesiones Fotográficas: Estilo y Elegancia en Cada Toma

Si buscas darle un toque auténtico, elegante o retro a tus fotos, el alquiler de autos clásicos para sesiones fotográficas es la opción ideal. Este tipo de vehículos no solo son íconos del diseño automotriz, sino que se convierten en un elemento visual impactante que transforma cualquier sesión en una experiencia única.


¿Por Qué Usar Autos Clásicos en Sesiones Fotográficas?

1. Estética Visual Única

Un auto clásico aporta personalidad, historia y carácter a tus imágenes. Desde tomas urbanas hasta escenarios naturales, estos vehículos se adaptan a diferentes estilos visuales.

2. Ideal para Diversos Usos

  • Sesiones de boda y pre-boda
  • Campañas publicitarias
  • Editoriales de moda
  • Proyectos cinematográficos
  • Contenido para redes sociales

3. Variedad de Modelos

Desde convertibles vintage hasta muscle cars de los años 60 y 70, puedes elegir el modelo que mejor se ajuste a la estética de tu sesión.


Beneficios del Alquiler Profesional

  • Vehículos en excelente estado estético y mecánico
  • Choferes disponibles si se requiere movilidad
  • Asesoría para elegir el modelo adecuado
  • Posibilidad de ambientación adicional (flores, letreros, decoración retro)

Conclusión: Captura Momentos con Estilo

Un auto clásico puede transformar tu sesión fotográfica en una obra de arte visual. No importa el propósito: el estilo, la elegancia y el impacto están garantizados.


📸 ¡Reserva tu auto clásico y crea fotos memorables!

Consulta disponibilidad y haz de tu sesión algo realmente especial. ¡Llama la atención con cada toma!

Not Found

404

Sorry, the page you’re looking for doesn’t exist.