Przeglądaj źródła

d.legend.vect: move from addons to trunk

git-svn-id: https://svn.osgeo.org/grass/grass/trunk@69191 15284696-431f-4ddb-bdfa-cd5b030d7da7
Anna Petrášová 8 lat temu
rodzic
commit
6584ef50d8

+ 1 - 0
display/Makefile

@@ -18,6 +18,7 @@ SUBDIRS = \
 	d.info \
 	d.labels \
 	d.legend \
+	d.legend.vect \
 	d.linegraph \
 	d.mon \
 	d.northarrow \

+ 12 - 0
display/d.legend.vect/Makefile

@@ -0,0 +1,12 @@
+MODULE_TOPDIR = ../..
+
+PGM = d.legend.vect
+
+LIBES = $(DISPLAYLIB) $(GISLIB) $(SYMBLIB) 
+DEPENDENCIES = $(DISPLAYDEP) $(GISDEP) $(SYMBDEP)
+EXTRA_INC = $(VECT_INC)
+EXTRA_CFLAGS = $(VECT_CFLAGS)
+
+include $(MODULE_TOPDIR)/include/Make/Module.make
+
+default: cmd

+ 98 - 0
display/d.legend.vect/d.legend.vect.html

@@ -0,0 +1,98 @@
+<h2>DESCRIPTION</h2>
+Module <em>d.legend.vect</em> draws vector legend of currently displayed vector maps.
+<p>
+Parameter <b>at</b> defines the screen position of upper-left legend corner.
+Parameter <b>columns</b> defines the number of legend columns.
+User can specify a title of the legend using parameter <b>title</b>.
+The font of the title can be changed with <b>title_font</b>, <b>title_fontsize</b>.
+Flag <b>-b</b> is used to draw background of specified color (<b>bgcolor</b>),
+border color and border width (<b>border_color</b> and <b>border_width</b>).
+Parameter <b>symbol_size</b> defines the size of line and area symbols.
+The size of point symbols is based on currently set symbology of vector maps using
+<em><a href="d.vect.html">d.vect</a></em>.
+<p>Module <em>d.vect.legend</em> supports subtitles (see section Notes).
+Their font and font size can be set using parameters <b>sub_font</b>
+and <b>sub_fontsize</b>.
+
+<h3>Changing legend symbols and labels</h3>
+Symbols for vector areas and lines, and labels for individual vector labels
+can be changed in the symbology setting of each vector map in
+<em><a href="d.vect.html">d.vect</a></em> module (in Legend tab). Use its parameters
+<b>icon_area</b> and <b>icon_line</b> to pick from available symbols.
+By using parameter <b>legend_label</b> of <em>d.vect</em> module, users can change
+the default label, which is the map name.
+
+<h3>Modifying the order of legend entries and omitting certain vector maps
+from legend</h3>
+Module <em><a href="d.vect.html">d.vect</a></em> has a flag <b>-l</b>
+which when used removes the particular vector from vector legend.
+<p>The order of entries is defined by the order in Layer Manager (if used
+in GRASS GIS GUI). If that's not desired, one can export the legend file
+into a text file using parameter <b>output</b>, change the order of entries
+(see section Notes for format description) and then upload the modified file
+with parameter <b>input</b>.
+Parameter <b>output</b> defines path to the file where the internal legend
+file will be saved to, <b>input</b> defines the input file which
+the vector legend will be based on (input file must have correct format).
+
+<h2>NOTES</h2>
+Module <em>d.legend.vect</em> draws vector legend based on legend file defined
+in shell environment variable GRASS_LEGEND_FILE.
+This file is automatically created and updated whenever
+<em><a href="d.vect.html">d.vect</a></em> command is used.
+User can create custom legend file and then use 
+<em>export GRASS_LEGEND_FILE=path/to/file</em> in shell.
+GRASS GUI and MONITORS create the legend file automatically.
+By default the legend file is stored in grassdata/location/mapset/.tmp/user
+directory (in case of d.mon deeper in /monitor_name directory).<br>
+<p>
+Legend file has this format:
+<pre>
+label|symbol_name|feature_color|fill_color|size|line_width|geometry_type|feature_count
+</pre>
+Here is an example of legend file with subtitles:
+<pre>
+Infrastructure|||||||
+major roads|legend/line|5|black|200:200:200|2|line|355
+bridges|extra/bridge|15|black|black|1|point|10938
+Hydrology|||||||
+streams|legend/line_crooked|5|30:144:255|200:200:200|3|line|8554
+water bodies|legend/area_curved|5|none|30:144:255|1|area|27764
+</pre>
+<img alt="Example of subheadings used in vector legend"
+ src="d_legend_vect_subheadings.png">
+
+<h2>EXAMPLES</h2>
+Open cairo monitor to render to file:
+<div class="code"><pre>
+g.region vector=nc_state
+d.mon cairo
+d.vect map=nc_state color=26:26:26 fill_color=229:229:229 width=2 legend_label="state boundaries"
+d.vect map=urbanarea color=none fill_color=127:127:127 width=1 legend_label="urban areas"
+d.vect map=railroads color=red width=1
+d.vect map=hospitals color=77:77:77 fill_color=0:187:0 width=1 icon=basic/cross3 size=10
+d.legend.vect -b at=2,40 title="Hospitals in North Carolina" symbol_size=26 fontsize=16 title_fontsize=20
+</pre></div>
+
+<center>
+<img src="d_legend_vect.png" alt="d.legend.vect example"><br>
+</center>
+
+<h2>SEE ALSO</h2>
+
+<em>
+<a href="d.vect.html">d.vect</a>,
+<a href="d.legend.html">d.legend</a>
+</em>
+
+<p>
+Check also Python module from
+AddOns: <em><a href="http://grass.osgeo.org/grass70/manuals/addons/d.vect.thematic2.html">d.vect.thematic2</a></em>
+
+<h2>AUTHOR</h2>
+
+Adam Laza, during GSoC 2016
+Mentors: Anna Petrasova, Vaclav Petras, Martin Landa
+
+<p>
+<i>Last changed: $Date: 2015-08-11 23:06:03 +0200 (Út, 11 srp 2015) $</i>

BIN
display/d.legend.vect/d_legend_vect.png


BIN
display/d.legend.vect/d_legend_vect_subheadings.png


+ 283 - 0
display/d.legend.vect/draw.c

@@ -0,0 +1,283 @@
+/* draw.c:
+ *
+ *    With do_bg=1 compute position of all legend graphic item and draw only background.
+ *    Eith do_bg=0 compute position of all legend graphic item and draw all.
+ *
+ *    Copyright (C) 2016 by Adam Laza, GSoC 2016, and the GRASS Development Team*
+ *    This program is free software under the GPL (>=v2)
+ *    Read the COPYING file that comes with GRASS for details.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+#include <grass/display.h>
+#include <grass/glocale.h>
+#include <grass/colors.h>
+#include "local_proto.h"
+
+void draw(char *file_name, double LL, double LT, char *title, int cols, int bgcolor,
+          int bcolor, int bg_width, int do_bg, char* tit_font, int tit_size, char *sub_font,
+          int sub_size, char *font, int fontsize, int fontcolor, int symb_size, char *sep)
+{
+    double db, dt, dl, dr;
+    double bb, bt, bl, br;
+    double x0, y0;
+    double offs_y, row_ind, offs_x;
+    double x, y;
+    FILE *file_in;
+    char buf[BUFFSIZE];
+    int got_new;
+    SYMBOL *Symb;
+    char *symb_name, *line_color_str, *fill_color_str, *label, *type_str;
+    double size, line_width;
+    double row_w, text_h, title_h, title_w;
+    RGBA_Color *line_color, *fill_color;
+    int ret, R, G, B;
+    char *part, *sub_delim;
+    double maxlblw, sym_lbl_space;
+    double symb_h, symb_w, def_symb_h, def_symb_w;
+    int item_count, item;
+    double it_per_col;
+    double margin, bg_h, bg_w;
+    char **tokens;
+
+
+    D_get_src(&dt, &db, &dl, &dr);
+    x0 = dl + (int)((dr - dl) * LL / 100.);
+    y0 = dt + (int)((db - dt) * (100 - LT) / 100.);
+
+    /* Draw title */
+    title_h = 0;
+    if (strlen(title) > 0) {
+        D_font(tit_font);
+        D_text_size(tit_size, tit_size);
+        D_get_text_box(title, &bb, &bt, &bl, &br);
+        margin = 10;
+        title_h = bb - bt + margin;
+        title_w = br - bl;
+        if (! do_bg) {
+            x = x0;
+            y = y0 + title_h;
+            D_pos_abs(x, y);
+            D_use_color(fontcolor);
+            D_text(title);
+        }
+    }
+
+    file_in = fopen(file_name, "r");
+    sub_delim = G_malloc(GNAME_MAX);
+    snprintf(sub_delim, sizeof(GNAME_MAX), "%s%s%s%s%s", sep, sep, sep, sep, sep);
+    if (!file_in)
+        G_fatal_error(_("Unable to open input file <%s>"), file_name);
+
+    /* Get number of legend row(item) and the biggest symbol*/
+    item_count = 0;
+    def_symb_w = symb_size;
+
+    got_new = G_getl2(buf, sizeof(buf), file_in);
+    G_strip(buf);
+    while (got_new) {
+        if (strstr(buf, sub_delim) == NULL) {
+            /* Get the maximum symbol size */
+            tokens = G_tokenize(buf, sep);
+            symb_name = G_store(tokens[1]);
+            size = atof(tokens[2]);
+            type_str = G_store(tokens[6]);
+            G_free_tokens(tokens);
+
+            /* Symbol */
+            if (((strcmp(type_str,"point") != 0) && (strcmp(type_str, "centroid") != 0)) || size < 0) {
+                size = symb_size;
+            }
+            Symb = S_read(symb_name);
+            if (Symb == NULL)
+                G_warning(_("Cannot read symbol"));
+            else
+                S_stroke(Symb, size, 0, 0);
+            symb_w = size;
+
+            if (symb_w > def_symb_w)
+                def_symb_w = symb_w;
+        }
+        item_count++;
+        got_new = G_getl2(buf, sizeof(buf), file_in);
+        G_strip(buf);
+    }
+    rewind(file_in);
+    it_per_col = ceil(item_count / (cols * 1.0));
+
+    bg_h = 0;
+    maxlblw = 0;
+    offs_y = title_h;
+    sym_lbl_space = 10;
+    def_symb_h = symb_size;
+    item = 0;
+    offs_x = 0;
+    margin = 10;
+
+    got_new = G_getl2(buf, sizeof(buf), file_in);
+    G_strip(buf);
+
+    while (got_new) {
+        if (item < it_per_col){
+            row_ind = 5;
+            item++;
+        }
+        else {
+            if (bg_h < offs_y)
+                bg_h = offs_y + def_symb_h/2.;
+            offs_x += maxlblw + margin;
+            offs_y = title_h + row_ind;
+            maxlblw = 0;
+            item = 1;
+            row_ind = 0;
+        }
+        if (strstr(buf, sub_delim) != NULL) {
+            /* Group subtitle */
+            label = G_malloc(GNAME_MAX);
+            part = strtok(buf, sep);
+            label = G_store(part);
+
+            D_text_size(sub_size, sub_size);
+            D_font(sub_font);
+            D_get_text_box(label, &bb, &bt, &bl, &br);
+            text_h = bb - bt;
+            row_w = br - bl;
+            offs_y += text_h + row_ind;
+            if (bg_h < offs_y)
+                bg_h = offs_y + def_symb_h/2.;
+            if (row_w > maxlblw)
+                maxlblw = row_w;
+
+            if (! do_bg) {
+                x = x0 + offs_x;
+                y = y0 + offs_y;
+                D_pos_abs(x, y);
+                D_use_color(fontcolor);
+                D_text(label);
+            }
+        }
+        else {
+            /* Map layers */
+            line_color = G_malloc(sizeof(RGBA_Color));
+            fill_color = G_malloc(sizeof(RGBA_Color));
+
+            tokens = G_tokenize(buf, sep);
+            label = G_store(tokens[0]);
+            symb_name = G_store(tokens[1]);
+            size = atof(tokens[2]);
+            line_color_str = G_store(tokens[3]);
+            fill_color_str = G_store(tokens[4]);
+            line_width = atof(tokens[5]);
+            type_str = G_store(tokens[6]);
+            G_free_tokens(tokens);
+
+            /* Symbol */
+            if (((strcmp(type_str,"point") != 0) && (strcmp(type_str, "centroid") != 0)) || size < 0) {
+                size = symb_size;
+            }
+            Symb = S_read(symb_name);
+            if (Symb == NULL)
+                G_warning(_("Cannot read symbol"));
+            else
+                S_stroke(Symb, size, 0, 0);
+
+            /* parse line color */
+            ret = G_str_to_color(line_color_str, &R, &G, &B);
+            line_color->r = (unsigned char)R;
+            line_color->g = (unsigned char)G;
+            line_color->b = (unsigned char)B;
+            if (ret == 1)
+                /* here alpha is only used as an on/off switch, otherwise unused by the display drivers */
+                line_color->a = RGBA_COLOR_OPAQUE;
+            else if (ret == 2)
+                line_color->a = RGBA_COLOR_NONE;
+            else
+                G_warning(_("[%s]: No such color"), line_color_str);
+            /* parse fill color */
+            ret = G_str_to_color(fill_color_str, &R, &G, &B);
+            fill_color->r = (unsigned char)R;
+            fill_color->g = (unsigned char)G;
+            fill_color->b = (unsigned char)B;
+            if (ret == 1)
+                fill_color->a = RGBA_COLOR_OPAQUE;
+            else if (ret == 2)
+                fill_color->a = RGBA_COLOR_NONE;
+            else
+                G_warning(_("[%s]: No such color"), fill_color_str);
+
+            /* Label */
+            D_text_size(fontsize, fontsize);
+            D_font(font);
+            D_get_text_box(label, &bb, &bt, &bl, &br);
+
+            symb_h = size;
+            if (symb_h < def_symb_h)
+                symb_h = def_symb_h;
+
+            text_h = bb - bt;
+            row_w = def_symb_w + sym_lbl_space + br - bl;
+            if (symb_h >= text_h)
+                offs_y += symb_h + row_ind;
+            else
+                offs_y += text_h + row_ind;
+
+            if (bg_h <= offs_y)
+                bg_h = offs_y + symb_h/2.;
+            if (row_w > maxlblw)
+                maxlblw = row_w;
+
+            if (! do_bg) {
+                S_stroke(Symb, size, 0, 0);
+                x = x0 + offs_x + def_symb_w/2.;
+                y = y0 + offs_y - symb_h/2;
+                D_line_width(line_width);
+                D_symbol(Symb, x, y, line_color, fill_color);
+
+                x = x0 + offs_x + def_symb_w + sym_lbl_space;
+                y = y0 + offs_y - symb_h/2. + text_h/2.;
+                D_pos_abs(x, y);
+                D_use_color(fontcolor);
+                D_text(label);
+            }
+        }
+
+        got_new = G_getl2(buf, sizeof(buf), file_in);
+        G_strip(buf);
+    }
+
+    fclose(file_in);
+
+    /* Draw background */
+    if (do_bg) {
+        double x0bg, y0bg, x1bg, y1bg;
+        if (title_w > offs_x + maxlblw)
+            bg_w = title_w;
+        else
+            bg_w = offs_x + maxlblw;
+
+        x0bg = x0 - margin;
+        y0bg = y0;
+        x1bg = x0 + bg_w + margin;
+        y1bg = y0 + bg_h;
+
+        if (bgcolor) {
+            D_use_color(bgcolor);
+            D_box_abs(x0bg, y0bg, x1bg, y1bg);
+        }
+
+        D_use_color(bcolor);
+        D_line_width(bg_width);
+        D_begin();
+        D_move_abs(x0bg, y0bg);
+        D_cont_abs(x0bg, y1bg);
+        D_cont_abs(x1bg, y1bg);
+        D_cont_abs(x1bg, y0bg);
+        D_close();
+        D_end();
+        D_stroke();
+    }
+
+    D_save_command(G_recreate_command());
+}

+ 5 - 0
display/d.legend.vect/local_proto.h

@@ -0,0 +1,5 @@
+#define BUFFSIZE 512
+
+/* draw.c */
+void draw(char *, double, double, char *, int, int, int, int,
+          int, char *, int, char *, int, char *, int, int, int, char *);

+ 292 - 0
display/d.legend.vect/main.c

@@ -0,0 +1,292 @@
+/*
+ ****************************************************************************
+ *
+ * MODULE:       d.vect.legend
+ * AUTHOR(S):    Adam Laza, CTU, GSoC 2016
+ * PURPOSE:      Display a vector layer
+ * COPYRIGHT:    (C) 2007-2016 by the GRASS Development Team
+ *
+ *               This program is free software under the GNU General Public
+ *               License (>=v2). Read the file COPYING that comes with GRASS
+ *               for details.
+ *
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <grass/display.h>
+#include <grass/glocale.h>
+#include "local_proto.h"
+
+
+int main(int argc, char **argv)
+{
+    struct GModule *module;
+//    struct Option *opt_input, *opt_sep;
+    struct Option *opt_at, *opt_cols, *opt_font, *opt_fontsize,
+            *opt_fontcolor, *opt_title, *opt_tit_font, *opt_tit_fontsize, *opt_sub_font,
+            *opt_sub_fontsize, *opt_bcolor, *opt_bgcolor, *opt_symb_size,
+            *opt_bg_width, *opt_output, *opt_input, *opt_sep;
+    struct Flag *fl_bg;
+
+    double LL, LT;
+    char *title, *file_name;
+    int bcolor, bgcolor, do_bg;
+    int fontsize, fontcolor, tit_size, sub_size;
+    char *font, *tit_font, *sub_font;
+    int cols, symb_size, bg_width;
+    char *out_file;
+    FILE *source;
+    char buf[BUFFSIZE];
+    char *sep;
+    size_t nread;
+
+
+    /* Initialize the GIS calls */
+    G_gisinit(argv[0]);
+
+    module = G_define_module();
+    G_add_keyword(_("display"));
+    G_add_keyword(_("cartography"));
+    G_add_keyword(_("vector"));
+    G_add_keyword(_("legend"));
+    module->description =
+    _("Displays a vector legend "
+      "in the active graphics frame.");
+
+    opt_at = G_define_option();
+    opt_at->key = "at";
+    opt_at->key_desc = "left,top";
+    opt_at->type = TYPE_DOUBLE;
+    opt_at->options = "0-100";
+    opt_at->answer = "10,40";
+    opt_at->required = NO;
+    opt_at->description =
+    _("Screen position of legend to be drawn (percentage, [0,0] is lower left)");
+
+    opt_cols = G_define_option();
+    opt_cols->key = "columns";
+    opt_cols->type = TYPE_INTEGER;
+    opt_cols->answer = "1";
+    opt_cols->required = NO;
+    opt_cols->description =
+    _("Number of legend columns");
+    opt_cols->guisection = _("Layout");
+
+    opt_title = G_define_option();
+    opt_title->key = "title";
+    opt_title->type = TYPE_STRING;
+    opt_title->required = NO;
+    opt_title->description = _("Legend title");
+    opt_title->guisection = _("Title");
+
+    opt_symb_size = G_define_option();
+    opt_symb_size->key = "symbol_size";
+    opt_symb_size->type = TYPE_INTEGER;
+    opt_symb_size->required = NO;
+    opt_symb_size->description = _("Symbol size");
+    opt_symb_size->answer = "20";
+    opt_symb_size->guisection = _("Layout");
+
+    opt_bcolor = G_define_standard_option(G_OPT_CN);
+    opt_bcolor->key = "border_color";
+    opt_bcolor->answer = "black";
+    opt_bcolor->label = _("Border color");
+    opt_bcolor->guisection = _("Background");
+
+    opt_bgcolor = G_define_standard_option(G_OPT_CN);
+    opt_bgcolor->key = "bgcolor";
+    opt_bgcolor->answer = "white";
+    opt_bgcolor->label = _("Background color");
+    opt_bgcolor->guisection = _("Background");
+
+    opt_bg_width = G_define_option();
+    opt_bg_width->type = TYPE_INTEGER;
+    opt_bg_width->key = "border_width";
+    opt_bg_width->answer = "2";
+    opt_bg_width->label = _("Background border width");
+    opt_bg_width->guisection = _("Background");
+
+    opt_font = G_define_option();
+    opt_font->key = "font";
+    opt_font->type = TYPE_STRING;
+    opt_font->required = NO;
+    opt_font->description = _("Font name");
+    opt_font->guisection = _("Font settings");
+
+    opt_fontsize = G_define_option();
+    opt_fontsize->key = "fontsize";
+    opt_fontsize->type = TYPE_DOUBLE;
+    opt_fontsize->required = NO;
+    opt_fontsize->options = "1-360";
+    opt_fontsize->label = _("Font size");
+    opt_fontsize->description = _("Default: 12");
+    opt_fontsize->guisection = _("Font settings");
+
+    opt_tit_font = G_define_option();
+    opt_tit_font->key = "title_font";
+    opt_tit_font->type = TYPE_STRING;
+    opt_tit_font->required = NO;
+    opt_tit_font->description = _("Title font name");
+    opt_tit_font->guisection = _("Font settings");
+
+    opt_tit_fontsize = G_define_option();
+    opt_tit_fontsize->key = "title_fontsize";
+    opt_tit_fontsize->type = TYPE_DOUBLE;
+    opt_tit_fontsize->required = NO;
+    opt_tit_fontsize->options = "1-360";
+    opt_tit_fontsize->label = _("Title font size");
+    opt_tit_fontsize->description = _("Default: 18");
+    opt_tit_fontsize->guisection = _("Title");
+
+    opt_sub_font = G_define_option();
+    opt_sub_font->key = "sub_font";
+    opt_sub_font->type = TYPE_STRING;
+    opt_sub_font->required = NO;
+    opt_sub_font->description = _("Subtitle font name");
+    opt_sub_font->guisection = _("Font settings");
+
+    opt_sub_fontsize = G_define_option();
+    opt_sub_fontsize->key = "sub_fontsize";
+    opt_sub_fontsize->type = TYPE_DOUBLE;
+    opt_sub_fontsize->required = NO;
+    opt_sub_fontsize->options = "1-360";
+    opt_sub_fontsize->label = _("Subtitle font size");
+    opt_sub_fontsize->description = _("Default: 14");
+    opt_sub_fontsize->guisection = _("Font settings");
+
+    opt_fontcolor = G_define_standard_option(G_OPT_C);
+    opt_fontcolor->key = "fontcolor";
+    opt_fontcolor->answer = "black";
+    opt_fontcolor->label = _("Font color");
+    opt_fontcolor->guisection = _("Font settings");
+
+    fl_bg = G_define_flag();
+    fl_bg->key = 'b';
+    fl_bg->description = _("Display legend background");
+    fl_bg->guisection = _("Background");
+
+    opt_input = G_define_standard_option(G_OPT_F_INPUT);
+    opt_input->label = _("Input legend file");
+    opt_input->description = _("Path to legend file ");
+    opt_input->required = NO;
+    opt_input->guisection = _("In/Out");
+
+    opt_output = G_define_standard_option(G_OPT_F_OUTPUT);
+    opt_output->label = _("Output csv file");
+    opt_output->description = _("Path to output file or '-' "
+                                "for standard output");
+    opt_output->required = NO;
+    opt_output->guisection = _("In/Out");
+
+    opt_sep = G_define_standard_option(G_OPT_F_SEP);
+    opt_sep->guisection = _("In/Out");
+
+    /* Check command line */
+    if (G_parser(argc, argv)) {
+        exit(EXIT_FAILURE);
+    }
+
+    D_open_driver();
+    D_setup_unity(0);
+
+    /* parse and check options and flags */
+    if (opt_at->answer) {
+        sscanf(opt_at->answers[0], "%lf", &LL);
+        sscanf(opt_at->answers[1], "%lf", &LT);
+    }
+    else {
+        LL = 10;
+        LT = 40;
+    }
+
+    if (opt_title->answer)
+        title = opt_title->answer;
+    else
+        title = "";
+
+    if (opt_cols->answer)
+        sscanf(opt_cols->answer, "%d", &cols);
+    else
+        cols = 1;
+
+    sscanf(opt_symb_size->answer, "%d", &symb_size);
+    sscanf(opt_bg_width->answer, "%d", &bg_width);
+
+    /* Background */
+    do_bg = fl_bg->answer;
+    bcolor = D_parse_color(opt_bcolor->answer, TRUE);
+    bgcolor = D_parse_color(opt_bgcolor->answer, TRUE);
+
+    /* Font settings */
+    if (opt_font->answer)
+        font = opt_font->answer;
+    else
+        font = "sans";
+    if (opt_fontsize->answer != NULL)
+        sscanf(opt_fontsize->answer, "%d", &fontsize);
+    else
+        fontsize = 14;
+
+    if (opt_tit_font->answer)
+        tit_font = opt_tit_font->answer;
+    else
+        tit_font = font;
+    if (opt_tit_fontsize->answer)
+        sscanf(opt_tit_fontsize->answer, "%d", &tit_size);
+    else
+        tit_size = fontsize;
+
+    if (opt_sub_font->answer)
+        sub_font = opt_sub_font->answer;
+    else
+        sub_font = font;
+    if (opt_sub_fontsize->answer)
+        sscanf(opt_sub_fontsize->answer, "%d", &sub_size);
+    else
+        sub_size = fontsize;
+
+    fontcolor = D_parse_color(opt_fontcolor->answer, FALSE); /*default color: black */
+
+    /* I/O */
+    sep = G_option_to_separator(opt_sep);
+
+    if (opt_input->answer) {
+        file_name = opt_input->answer;
+        if (!file_name)
+            G_fatal_error(_("Unable to open input file <%s>"), file_name);
+    }
+    else {
+        file_name = getenv("GRASS_LEGEND_FILE");
+        if (!file_name)
+            G_fatal_error("No legend file defined.");
+    }
+
+
+    if (opt_output->answer) {
+        if (strcmp(opt_output->answer,"-") == 0) {
+            source = fopen(file_name, "r");
+            if (!source)
+                G_fatal_error(_("Unable to open input file <%s>"), file_name);
+            while ((nread = fread(buf, 1, sizeof(buf), source)))
+                fwrite(buf, 1, nread, stdout);
+            fclose(source);
+        }
+        else {
+            out_file = opt_output->answer;
+            G_copy_file(file_name, out_file);
+        }
+    }
+
+    /* Pre-calculate the layout */
+    if (do_bg)
+        draw(file_name, LL, LT, title, cols, bgcolor, bcolor, bg_width, 1, tit_font, tit_size, sub_font, sub_size, font, fontsize, fontcolor, symb_size, sep);
+
+    /* Draw legend */
+    draw(file_name, LL, LT, title, cols, bgcolor, bcolor, bg_width, 0, tit_font, tit_size, sub_font, sub_size, font, fontsize, fontcolor, symb_size, sep);
+
+    D_close_driver();
+
+    exit(EXIT_SUCCESS);
+}