~ubuntu-branches/ubuntu/vivid/grass/vivid-proposed

« back to all changes in this revision

Viewing changes to display/d.text/main.c

  • Committer: Package Import Robot
  • Author(s): Bas Couwenberg
  • Date: 2015-02-20 23:12:08 UTC
  • mfrom: (8.2.6 experimental)
  • Revision ID: package-import@ubuntu.com-20150220231208-1u6qvqm84v430b10
Tags: 7.0.0-1~exp1
* New upstream release.
* Update python-ctypes-ternary.patch to use if/else instead of and/or.
* Drop check4dev patch, rely on upstream check.
* Add build dependency on libpq-dev to grass-dev for libpq-fe.h.
* Drop patches applied upstream, refresh remaining patches.
* Update symlinks for images switched from jpg to png.

Show diffs side-by-side

added added

removed removed

Lines of Context:
4
4
 * MODULE:       d.text
5
5
 *
6
6
 * AUTHOR(S):    James Westervelt, US Army CERL
 
7
 *               Updated by Huidae Cho, Markus Neteler
7
8
 *
8
9
 * PURPOSE:      display text in active frame
9
10
 *
10
11
 * COPYRIGHT:    (C) 2001 by the GRASS Development Team
11
12
 *
12
13
 *               This program is free software under the GNU General Public
13
 
 *              License (>=v2). Read the file COPYING that comes with GRASS
14
 
 *              for details.
 
14
 *               License (>=v2). Read the file COPYING that comes with GRASS
 
15
 *               for details.
15
16
 *
16
17
 *****************************************************************************/
17
18
 
18
19
/*
19
 
 *   d.text
 
20
 *   d.text commands:
20
21
 *
21
 
 *   Draw text in a text window.   Text lines come from stdin.
22
 
 *   R_text control:
23
 
 *      .C color_name        change color
24
 
 *      .S size              change text size
25
 
 *      .B 0                 bold (double print) off
26
 
 *      .B 1                 bold (double print) on
27
 
 *      .F name              change font to name
 
22
 *      .F {font|path}[:charset]                font
 
23
 *      .C {color_name|RR:GG:BB|0xRRGGBB}       color
 
24
 *      .G {color_name|RR:GG:BB|0xRRGGBB}       background color
 
25
 *      .S [+|-]size[p]                         text size
 
26
 *                                              +/-: relative size
 
27
 *                                              p: size in pixels
 
28
 *      .B {0|1}                                bold (double print) off/on
 
29
 *      .A {ll|lc|lr|cl|cc|cr|ul|uc|ur}         align (TODO)
 
30
 *      .R [+|-]rotation[r]                     rotation
 
31
 *                                              +/-: relative rotation
 
32
 *                                              r: angle in radian
 
33
 *      .I linespacing                          linespacing
 
34
 *      .X [+|-]x[%|p]                          x: relative to x origin
 
35
 *                                              +/-: relative dx
 
36
 *                                              %: percentage
 
37
 *                                              p: pixels
 
38
 *      .Y [+|-]y[%|p]                          y: relative to y origin
 
39
 *                                              +/-: relative dy
 
40
 *                                              %: percentage
 
41
 *                                              p: pixels
 
42
 *      .L {0|1}                                linefeed off/on
 
43
 *      .E [+|-]east[%|p]                       x origin: geographic coordinates
 
44
 *                                              +/-: relative de
 
45
 *                                              %: percentage
 
46
 *                                              p: pixels
 
47
 *      .N [+|-]north[%|p]                      y origin: geographic coordinates
 
48
 *                                              +/-: relative dn
 
49
 *                                              %: percentage
 
50
 *                                              p: pixels
 
51
 *      ..                                      draw one dot (.)
 
52
 *      .<SPACE>                                comments
28
53
 */
29
54
 
 
55
#include <math.h>
30
56
#include <stdio.h>
31
57
#include <stdlib.h>
32
58
#include <string.h>
33
59
#include <unistd.h>
34
60
#include <grass/gis.h>
35
61
#include <grass/display.h>
36
 
#include <grass/raster.h>
37
62
#include <grass/colors.h>
38
63
#include <grass/glocale.h>
39
64
 
 
65
#define BACKWARD_COMPATIBILITY
 
66
#define DEFAULT_COLOR "gray"
 
67
 
 
68
struct rectinfo
 
69
{
 
70
    double t, b, l, r;
 
71
};
 
72
 
 
73
static void set_color(char *);
 
74
static int get_coordinates(double *, double *, double *, double *,
 
75
                           struct rectinfo, char **, char, char);
 
76
static void draw_text(char *, double *, double *, double, char *, double, char, int, int, int);
 
77
 
40
78
int main(int argc, char **argv)
41
79
{
42
 
    char *cmd_ptr, *max_buff;
43
 
    char buff[512];
44
 
    char window_name[64];
45
 
    float size;
46
 
    int bold;
47
 
    int R, G, B, color = 0;
48
 
    int cur_dot_row, cur_dot_column;
49
 
    int dots_per_line;
50
 
    int start_line;
51
 
    int t, b, l, r;
52
 
    int tsize;
 
80
    struct GModule *module;
 
81
    struct
 
82
    {
 
83
        struct Option *text;
 
84
        struct Option *size;
 
85
        struct Option *fgcolor;
 
86
        struct Option *bgcolor;
 
87
        struct Option *line;
 
88
        struct Option *at;
 
89
        struct Option *rotation;
 
90
        struct Option *align;
 
91
        struct Option *linespacing;
 
92
        struct Option *font;
 
93
        struct Option *path;
 
94
        struct Option *charset;
 
95
        struct Option *input;
 
96
    } opt;
 
97
    struct
 
98
    {
 
99
        struct Flag *p;
 
100
        struct Flag *g;
 
101
        struct Flag *b;
 
102
        struct Flag *r;
 
103
        struct Flag *s;
 
104
    } flag;
 
105
 
 
106
    /* options and flags */
 
107
    char *text;
 
108
    double size;
53
109
    double x, y;
 
110
    int line;
54
111
    double rotation;
55
 
 
56
 
    struct GModule *module;
57
 
    struct Option *opt1, *opt2, *opt3, *opt4, *opt5;
58
 
    struct Flag *flag_b;
59
 
    char *wind_file_name;
60
 
    FILE *wind_file;
61
 
 
62
 
    /* Initialize the GIS calls */
 
112
    char align[3];
 
113
    double linespacing;
 
114
 
 
115
    char bold;
 
116
 
 
117
    /* window info */
 
118
    struct rectinfo win;
 
119
 
 
120
    /* command file */
 
121
    FILE *cmd_fp;
 
122
 
 
123
    char buf[512];
 
124
 
 
125
    int first_text;
 
126
    int linefeed;
 
127
    int set_l;
 
128
    double orig_x, orig_y;
 
129
    double prev_x, prev_y;
 
130
    double set_x, set_y;
 
131
    double east, north;
 
132
    int do_background, fg_color, bg_color;
 
133
 
 
134
    /* initialize the GIS calls */
63
135
    G_gisinit(argv[0]);
64
136
 
65
137
    module = G_define_module();
66
 
    module->keywords = _("display, cartography");
 
138
    G_add_keyword(_("display"));
 
139
    G_add_keyword(_("cartography"));
67
140
    module->description =
68
141
        _("Draws text in the active display frame on the graphics monitor using the current font.");
69
142
 
70
 
    opt1 = G_define_option();
71
 
    opt1->key = "size";
72
 
    opt1->type = TYPE_DOUBLE;
73
 
    opt1->required = NO;
74
 
    opt1->answer = "5";
75
 
    opt1->options = "0-100";
76
 
    opt1->description =
 
143
    opt.text = G_define_option();
 
144
    opt.text->key = "text";
 
145
    opt.text->type = TYPE_STRING;
 
146
    opt.text->required = NO;
 
147
    opt.text->description = _("Text to display");
 
148
 
 
149
    opt.size = G_define_option();
 
150
    opt.size->key = "size";
 
151
    opt.size->type = TYPE_DOUBLE;
 
152
    opt.size->required = NO;
 
153
    opt.size->answer = "5";
 
154
    opt.size->options = "0-100";
 
155
    opt.size->description =
77
156
        _("Height of letters in percentage of available frame height");
78
157
 
79
 
    opt2 = G_define_option();
80
 
    opt2->key = "color";
81
 
    opt2->type = TYPE_STRING;
82
 
    opt2->answer = "gray";
83
 
    opt2->required = NO;
84
 
    opt2->description =
 
158
    opt.fgcolor = G_define_option();
 
159
    opt.fgcolor->key = "color";
 
160
    opt.fgcolor->type = TYPE_STRING;
 
161
    opt.fgcolor->answer = DEFAULT_COLOR;
 
162
    opt.fgcolor->required = NO;
 
163
    opt.fgcolor->description =
85
164
        _("Text color, either a standard GRASS color or R:G:B triplet");
86
 
    opt2->gisprompt = GISPROMPT_COLOR;
87
 
 
88
 
    opt3 = G_define_option();
89
 
    opt3->key = "line";
90
 
    opt3->required = NO;
91
 
    opt3->type = TYPE_INTEGER;
92
 
    opt3->options = "1-1000";
93
 
    opt3->description =
 
165
    opt.fgcolor->gisprompt = "old_color,color,color";
 
166
 
 
167
    opt.bgcolor = G_define_option();
 
168
    opt.bgcolor->key = "bgcolor";
 
169
    opt.bgcolor->type = TYPE_STRING;
 
170
    opt.bgcolor->required = NO;
 
171
    opt.bgcolor->description =
 
172
        _("Text background color, either a standard GRASS color or R:G:B triplet");
 
173
    opt.bgcolor->gisprompt = "old_color,color,color";
 
174
 
 
175
    opt.line = G_define_option();
 
176
    opt.line->key = "line";
 
177
    opt.line->required = NO;
 
178
    opt.line->type = TYPE_INTEGER;
 
179
    opt.line->options = "1-1000";
 
180
    opt.line->description =
94
181
        _("The screen line number on which text will begin to be drawn");
95
182
 
96
 
    opt4 = G_define_option();
97
 
    opt4->key = "at";
98
 
    opt4->key_desc = "x,y";
99
 
    opt4->type = TYPE_DOUBLE;
100
 
    opt4->options = "0-100";
101
 
    opt4->required = NO;
102
 
    opt4->description =
 
183
    opt.at = G_define_option();
 
184
    opt.at->key = "at";
 
185
    opt.at->key_desc = "x,y";
 
186
    opt.at->type = TYPE_DOUBLE;
 
187
    opt.at->required = NO;
 
188
    opt.at->description =
103
189
        _("Screen position at which text will begin to be drawn (percentage, [0,0] is lower left)");
104
190
 
105
 
    opt5 = G_define_option();
106
 
    opt5->key = "rotation";
107
 
    opt5->type = TYPE_DOUBLE;
108
 
    opt5->required = NO;
109
 
    opt5->answer = "0";
110
 
    opt5->description = _("Rotation angle in degrees (counter-clockwise)");
111
 
 
112
 
    flag_b = G_define_flag();
113
 
    flag_b->key = 'b';
114
 
    flag_b->description = _("Use bold text");
115
 
 
116
 
 
117
 
    /* Check command line */
 
191
    opt.align = G_define_option();
 
192
    opt.align->key = "align";
 
193
    opt.align->type = TYPE_STRING;
 
194
    opt.align->required = NO;
 
195
    opt.align->answer = "ll";
 
196
    opt.align->options = "ll,lc,lr,cl,cc,cr,ul,uc,ur";
 
197
    opt.align->description = _("Text alignment");
 
198
 
 
199
    opt.rotation = G_define_option();
 
200
    opt.rotation->key = "rotation";
 
201
    opt.rotation->type = TYPE_DOUBLE;
 
202
    opt.rotation->required = NO;
 
203
    opt.rotation->answer = "0";
 
204
    opt.rotation->description =
 
205
        _("Rotation angle in degrees (counter-clockwise)");
 
206
 
 
207
    opt.linespacing = G_define_option();
 
208
    opt.linespacing->key = "linespacing";
 
209
    opt.linespacing->type = TYPE_DOUBLE;
 
210
    opt.linespacing->required = NO;
 
211
    opt.linespacing->answer = "1.25";
 
212
    opt.linespacing->description = _("Line spacing");
 
213
 
 
214
    opt.font = G_define_option();
 
215
    opt.font->key = "font";
 
216
    opt.font->type = TYPE_STRING;
 
217
    opt.font->required = NO;
 
218
    opt.font->description = _("Font name");
 
219
 
 
220
    opt.path = G_define_standard_option(G_OPT_F_INPUT);
 
221
    opt.path->key = "path";
 
222
    opt.path->required = NO;
 
223
    opt.path->description = _("Path to font file");
 
224
    opt.path->gisprompt = "old,font,file";
 
225
 
 
226
    opt.charset = G_define_option();
 
227
    opt.charset->key = "charset";
 
228
    opt.charset->type = TYPE_STRING;
 
229
    opt.charset->required = NO;
 
230
    opt.charset->description =
 
231
        _("Text encoding (only applicable to TrueType fonts)");
 
232
 
 
233
    opt.input = G_define_standard_option(G_OPT_F_INPUT);
 
234
    opt.input->required = NO;
 
235
    opt.input->description = _("Input file");
 
236
 
 
237
    flag.p = G_define_flag();
 
238
    flag.p->key = 'p';
 
239
    flag.p->description = _("Screen position in pixels ([0,0] is top left)");
 
240
 
 
241
    flag.g = G_define_flag();
 
242
    flag.g->key = 'g';
 
243
    flag.g->description = _("Screen position in geographic coordinates");
 
244
 
 
245
    flag.b = G_define_flag();
 
246
    flag.b->key = 'b';
 
247
    flag.b->description = _("Use bold text");
 
248
 
 
249
    flag.r = G_define_flag();
 
250
    flag.r->key = 'r';
 
251
    flag.r->description = _("Use radians instead of degrees for rotation");
 
252
 
 
253
    flag.s = G_define_flag();
 
254
    flag.s->key = 's';
 
255
    flag.s->description = _("Font size is height in pixels");
 
256
 
 
257
 
 
258
    /* check command line */
118
259
    if (G_parser(argc, argv))
119
260
        exit(1);
120
261
 
121
 
    if (opt3->answer && opt4->answer)
 
262
    /* parse and check options and flags */
 
263
 
 
264
    if ((opt.line->answer && opt.at->answer) ||
 
265
        (flag.p->answer && flag.g->answer))
122
266
        G_fatal_error(_("Please choose only one placement method"));
123
267
 
124
 
 
125
 
    if (isatty(0))
126
 
        fprintf(stdout,
127
 
                "\nPlease enter text instructions.  Enter EOF (ctrl-d) on last line to quit\n");
128
 
 
129
 
    sscanf(opt1->answer, "%f", &size);
130
 
 
131
 
    if (R_open_driver() != 0)
132
 
        G_fatal_error(_("No graphics device selected"));
133
 
 
134
 
    /* Parse and select text color */
135
 
    if (sscanf(opt2->answer, "%d:%d:%d", &R, &G, &B) == 3) {
136
 
        if (R >= 0 && R < 256 && G >= 0 && G < 256 && B >= 0 && B < 256) {
137
 
            R_RGB_color(R, G, B);
138
 
            color = 1;          /* to make success test below happy */
139
 
        }
140
 
    }
141
 
    else {
142
 
        color = D_translate_color(opt2->answer);
143
 
        R_standard_color(color);
144
 
    }
145
 
 
146
 
    if (!color)
147
 
        G_fatal_error(_("[%s]: No such color"), opt2->answer);
148
 
 
149
 
    rotation = atof(opt5->answer);
150
 
 
151
 
    if (D_get_cur_wind(window_name))
152
 
        G_fatal_error(_("No current window"));
153
 
 
154
 
    if (D_set_cur_wind(window_name))
155
 
        G_fatal_error(_("Current window not available"));
156
 
 
157
 
    /* Figure out where to put text */
158
 
    D_get_screen_window(&t, &b, &l, &r);
159
 
    R_set_window(t, b, l, r);
160
 
 
161
 
    dots_per_line = (int)(size / 100.0 * (float)(b - t));
162
 
    tsize = (int)(.8 * (float)dots_per_line);
163
 
 
164
 
    if (!opt4->answer) {
165
 
        if (opt3->answer)
166
 
            sscanf(opt3->answer, "%d", &start_line);
167
 
        else
168
 
            start_line = 1;
169
 
 
170
 
        cur_dot_row = t + (start_line - 1) * dots_per_line;
171
 
        cur_dot_column = l + 5;
172
 
    }
173
 
    else {
174
 
        x = atof(opt4->answers[0]);
175
 
        y = atof(opt4->answers[1]);
176
 
        if (x < 0 || x > 100 || y < 0 || y > 100)
177
 
            G_fatal_error(_("value [%.0f,%.0f] out of range [0-100]"), x, y);
178
 
 
179
 
        cur_dot_row = t + (int)((b - t) * (100. - y) / 100.);
180
 
        cur_dot_column = l + (int)((r - l) * x / 100.);
181
 
    }
182
 
 
183
 
    R_text_size(tsize, tsize);
184
 
    R_text_rotation((float)rotation);
185
 
 
186
 
    if (flag_b->answer)
187
 
        bold = 1;
188
 
    else
189
 
        bold = 0;
190
 
 
191
 
    wind_file_name = G_tempfile();
192
 
    if ((wind_file = fopen(wind_file_name, "w")) == NULL)
193
 
        G_fatal_error(_("Unable to open temporary file <%s>"),
194
 
                      wind_file_name);
195
 
 
196
 
    /* Do the plotting */
197
 
    while (fgets(buff, 512, stdin)) {
198
 
        fprintf(wind_file, "%s", buff);
199
 
        if (*buff == '.') {
200
 
            for (cmd_ptr = buff + 2; *cmd_ptr == ' '; cmd_ptr++) ;
201
 
            G_squeeze(cmd_ptr); /* added 6/91 DBS @ CWU */
202
 
            switch (buff[1] & 0x7F) {
203
 
            case 'F':           /* font */
204
 
                R_font(cmd_ptr);
205
 
                break;
206
 
            case 'C':           /* color */
207
 
                if (sscanf(cmd_ptr, "%d:%d:%d", &R, &G, &B) == 3) {
208
 
                    if (R >= 0 && R < 256 && G >= 0 && G < 256 && B >= 0 &&
209
 
                        B < 256) {
210
 
                        R_RGB_color(R, G, B);
211
 
                    }
212
 
                }
213
 
                else if (color = D_translate_color(cmd_ptr))
214
 
                    R_standard_color(color);
215
 
                break;
216
 
            case 'S':           /* size */
217
 
                if (sscanf(cmd_ptr, "%f", &size)) {
218
 
                    dots_per_line = (int)(size / 100.0 * (float)(b - t));
219
 
                    tsize = (int)(.8 * (float)dots_per_line);
220
 
                    R_text_size(tsize, tsize);
221
 
                }
222
 
                break;
223
 
            case 'B':           /* bold */
224
 
                if (!sscanf(cmd_ptr, "%d", &bold))
225
 
                    bold = 0;
226
 
                break;
227
 
            case 'R':           /* rotation */
228
 
                if (sscanf(cmd_ptr, "%lf", &rotation)) {
229
 
                    R_text_rotation((float)rotation);
230
 
                }
231
 
                break;
232
 
            default:
233
 
                break;
234
 
            }
235
 
        }
236
 
        else {
237
 
            if (!opt4->answer)
238
 
                cur_dot_row += dots_per_line;
239
 
            R_move_abs(cur_dot_column, cur_dot_row);
240
 
            R_text(buff);
241
 
            if (bold) {
242
 
                R_move_abs(cur_dot_column, 1 + cur_dot_row);
243
 
                R_text(buff);
244
 
                R_move_abs(cur_dot_column + 1, cur_dot_row);
245
 
                R_text(buff);
246
 
            }
247
 
        }
248
 
    }
249
 
 
250
 
    R_text_size(5, 5);
251
 
 
252
 
    fclose(wind_file);
253
 
 
254
 
    max_buff =
255
 
        G_malloc(strlen(wind_file_name) + strlen(G_recreate_command()) + 4);
256
 
    sprintf(max_buff, "%s < %s", G_recreate_command(), wind_file_name);
257
 
    D_add_to_list(max_buff);
258
 
    G_free(max_buff);
259
 
 
260
 
    R_text_rotation(0.0);       /* reset */
261
 
    R_close_driver();
262
 
 
263
 
    exit(0);
 
268
    text = opt.text->answer;
 
269
 
 
270
    line = (opt.line->answer ? atoi(opt.line->answer) : 1);
 
271
 
 
272
    /* calculate rotation angle in radian */
 
273
    rotation = atof(opt.rotation->answer);
 
274
    if (!flag.r->answer)
 
275
        rotation *= M_PI / 180.0;
 
276
    rotation = fmod(rotation, 2.0 * M_PI);
 
277
    if (rotation < 0.0)
 
278
        rotation += 2.0 * M_PI;
 
279
 
 
280
    strncpy(align, opt.align->answer, 2);
 
281
    linespacing = atof(opt.linespacing->answer);
 
282
 
 
283
    bold = flag.b->answer;
 
284
 
 
285
    D_open_driver();
 
286
    
 
287
    if (opt.font->answer)
 
288
        D_font(opt.font->answer);
 
289
    else if (opt.path->answer)
 
290
        D_font(opt.path->answer);
 
291
 
 
292
    if (opt.charset->answer)
 
293
        D_encoding(opt.charset->answer);
 
294
 
 
295
    D_setup_unity(0);
 
296
 
 
297
    /* figure out where to put text */
 
298
    D_get_src(&win.t, &win.b, &win.l, &win.r);
 
299
 
 
300
    if (flag.s->answer)
 
301
        size = atof(opt.size->answer);
 
302
    else
 
303
#ifdef BACKWARD_COMPATIBILITY
 
304
        size = atof(opt.size->answer) / 100.0 * (win.b - win.t) / linespacing;
 
305
#else
 
306
        size = atof(opt.size->answer) / 100.0 * (win.b - win.t);
 
307
#endif
 
308
 
 
309
    fg_color = D_parse_color(opt.fgcolor->answer, TRUE);
 
310
    if (opt.bgcolor->answer) {
 
311
        do_background = 1;
 
312
        bg_color = D_parse_color(opt.bgcolor->answer, TRUE);
 
313
        if (bg_color == 0) /* ie color="none" */
 
314
            do_background = 0;
 
315
    } else
 
316
        do_background = 0;
 
317
    set_color(opt.fgcolor->answer);
 
318
 
 
319
    orig_x = orig_y = 0;
 
320
 
 
321
    if (opt.at->answer) {
 
322
        if (get_coordinates(&x, &y, &east, &north,
 
323
                            win, opt.at->answers,
 
324
                            flag.p->answer, flag.g->answer))
 
325
            G_fatal_error(_("Invalid coordinates"));
 
326
        orig_x = x;
 
327
        orig_y = y;
 
328
    }
 
329
    else {
 
330
        x = win.l + (size * linespacing + 0.5) - size;  /* d.text: +5 */
 
331
        y = win.t + line * (size * linespacing + 0.5);
 
332
    }
 
333
 
 
334
    prev_x = x;
 
335
    prev_y = y;
 
336
 
 
337
    D_text_size(size, size);
 
338
    D_text_rotation(rotation * 180.0 / M_PI);
 
339
 
 
340
    if (text) {
 
341
        double x2, y2;
 
342
 
 
343
        x2 = x;
 
344
        y2 = y;
 
345
 
 
346
        if (text[0])
 
347
            draw_text(text, &x2, &y2, size, align, rotation, bold, do_background, fg_color, bg_color);
 
348
 
 
349
        /* reset */
 
350
        D_text_size(5, 5);
 
351
        D_text_rotation(0.0);
 
352
 
 
353
        D_save_command(G_recreate_command());
 
354
        D_close_driver();
 
355
 
 
356
        exit(EXIT_SUCCESS);
 
357
    }
 
358
 
 
359
    if (!opt.input->answer || strcmp(opt.input->answer, "-") == 0)
 
360
        cmd_fp = stdin;
 
361
    else {
 
362
        cmd_fp = fopen(opt.input->answer, "r");
 
363
        if (!cmd_fp)
 
364
            G_fatal_error(_("Unable to open input file <%s>"), opt.input->answer);
 
365
    }
 
366
 
 
367
    if (isatty(fileno(cmd_fp)))
 
368
        fprintf(stderr,
 
369
                _("\nPlease enter text instructions.  Enter EOF (ctrl-d) on last line to quit\n"));
 
370
 
 
371
    set_x = set_y = set_l = 0;
 
372
    first_text = 1;
 
373
    linefeed = 1;
 
374
    /* do the plotting */
 
375
    while (fgets(buf, sizeof(buf), cmd_fp)) {
 
376
        int buf_len;
 
377
        char *buf_ptr, *ptr;
 
378
 
 
379
        buf_len = strlen(buf) - 1;
 
380
        for (; buf[buf_len] == '\r' || buf[buf_len] == '\n'; buf_len--) ;
 
381
        buf[buf_len + 1] = 0;
 
382
 
 
383
        if (buf[0] == '.' && buf[1] != '.') {
 
384
            int i;
 
385
            double d;
 
386
 
 
387
            G_squeeze(buf);     /* added 6/91 DBS @ CWU */
 
388
            for (buf_ptr = buf + 2; *buf_ptr == ' '; buf_ptr++) ;
 
389
            buf_len = strlen(buf_ptr);
 
390
 
 
391
            switch (buf[1] & 0x7f) {
 
392
            case 'F':
 
393
                /* font */
 
394
                if ((ptr = strchr(buf_ptr, ':')))
 
395
                    *ptr = 0;
 
396
                D_font(buf_ptr);
 
397
                if (ptr)
 
398
                    D_encoding(ptr + 1);
 
399
                break;
 
400
            case 'C':
 
401
                /* color */
 
402
                set_color(buf_ptr);
 
403
                fg_color = D_parse_color(buf_ptr, 1);
 
404
                break;
 
405
            case 'G':
 
406
                /* background color */
 
407
                bg_color = D_parse_color(buf_ptr, 1);
 
408
                do_background = 1;
 
409
                break;
 
410
            case 'S':
 
411
                /* size */
 
412
                i = 0;
 
413
                if (strchr("+-", buf_ptr[0]))
 
414
                    i = 1;
 
415
                d = atof(buf_ptr);
 
416
                if (buf_ptr[buf_len - 1] != 'p')
 
417
#ifdef BACKWARD_COMPATIBILITY
 
418
                    d *= (win.b - win.t) / 100.0 / linespacing;
 
419
#else
 
420
                    d *= (win.b - win.t) / 100.0;
 
421
#endif
 
422
                size = d + (i ? size : 0);
 
423
                D_text_size(size, size);
 
424
                break;
 
425
            case 'B':
 
426
                /* bold */
 
427
                bold = (atoi(buf_ptr) ? 1 : 0);
 
428
                break;
 
429
            case 'A':
 
430
                /* align */
 
431
                strncpy(align, buf_ptr, 2);
 
432
                break;
 
433
            case 'R':
 
434
                /* rotation */
 
435
                i = 0;
 
436
                if (strchr("+-", buf_ptr[0]))
 
437
                    i = 1;
 
438
                d = atof(buf_ptr);
 
439
                if (buf_ptr[buf_len - 1] != 'r')
 
440
                    d *= M_PI / 180.0;
 
441
                d += (i ? rotation : 0.0);
 
442
                rotation = fmod(d, 2.0 * M_PI);
 
443
                if (rotation < 0.0)
 
444
                    rotation += 2.0 * M_PI;
 
445
                D_text_rotation(rotation * 180.0 / M_PI);
 
446
                break;
 
447
            case 'I':
 
448
                /* linespacing */
 
449
                linespacing = atof(buf_ptr);
 
450
                break;
 
451
            case 'X':
 
452
                /* x */
 
453
                set_l = 0;
 
454
                set_x = 1;
 
455
                i = 0;
 
456
                if (strchr("+-", buf_ptr[0]))
 
457
                    i = 1;
 
458
                d = atof(buf_ptr);
 
459
                if (buf_ptr[buf_len - 1] == '%')
 
460
                    /* percentage */
 
461
                    d *= (win.r - win.l) / 100.0;
 
462
                else if (buf_ptr[buf_len - 1] != 'p')
 
463
                    /* column */
 
464
                    d = (d - 1) * size * linespacing + 0.5;
 
465
                x = prev_x = d + (i ? x : orig_x);
 
466
                break;
 
467
            case 'Y':
 
468
                /* y */
 
469
                set_l = 0;
 
470
                set_y = 1;
 
471
                i = 0;
 
472
                if (strchr("+-", buf_ptr[0]))
 
473
                    i = 1;
 
474
                d = atof(buf_ptr);
 
475
                if (buf_ptr[buf_len - 1] == '%')
 
476
                    /* percentage */
 
477
                    d = win.b - d * (win.b - win.t) / 100.0;
 
478
                else if (buf_ptr[buf_len - 1] != 'p')
 
479
                    /* row */
 
480
                    d *= size * linespacing + 0.5;
 
481
                y = prev_y = d + (i ? y : orig_y);
 
482
                break;
 
483
            case 'L':
 
484
                /* linefeed */
 
485
                set_l = 1;
 
486
                linefeed = (atoi(buf_ptr) ? 1 : 0);
 
487
                break;
 
488
            case 'E':
 
489
                i = 0;
 
490
                if (strchr("+-", buf_ptr[0]))
 
491
                    i = 1;
 
492
                d = atof(buf_ptr);
 
493
                if (buf_ptr[buf_len - 1] == '%')
 
494
                    d *= (win.r - win.l) / 100.0;
 
495
                else if (buf_ptr[buf_len - 1] != 'p')
 
496
                    d = D_u_to_d_col(d);
 
497
                x = prev_x = orig_x = d + (i ? orig_x : win.l);
 
498
                break;
 
499
            case 'N':
 
500
                i = 0;
 
501
                if (strchr("+-", buf_ptr[0]))
 
502
                    i = 1;
 
503
                d = atof(buf_ptr);
 
504
                if (buf_ptr[buf_len - 1] == '%')
 
505
                    d *= (win.b - win.t) / 100.0;
 
506
                else if (buf_ptr[buf_len - 1] != 'p')
 
507
                    d = D_u_to_d_row(d);
 
508
                y = prev_y = orig_y = d + (i ? orig_y : win.t);
 
509
                break;
 
510
            }
 
511
        }
 
512
        else {
 
513
            buf_ptr = buf;
 
514
            if (buf[0] == '.' && buf[1] == '.')
 
515
                buf_ptr++;
 
516
 
 
517
            if (!first_text && (linefeed || set_l)) {
 
518
                /* if x is not given, increment x */
 
519
                if (!set_x)
 
520
                    x = prev_x +
 
521
                        (size * linespacing + 0.5) * sin(rotation);
 
522
                /* if y is not given, increment y */
 
523
                if (!set_y)
 
524
                    y = prev_y +
 
525
                        (size * linespacing + 0.5) * cos(rotation);
 
526
                prev_x = x;
 
527
                prev_y = y;
 
528
            }
 
529
            set_x = set_y = set_l = first_text = 0;
 
530
 
 
531
            draw_text(buf_ptr, &x, &y, size, align, rotation, bold, do_background, fg_color, bg_color);
 
532
        }
 
533
    }
 
534
 
 
535
    if (cmd_fp != stdin)
 
536
        fclose(cmd_fp);
 
537
 
 
538
    /* reset */
 
539
    D_text_size(5, 5);
 
540
    D_text_rotation(0.0);
 
541
 
 
542
    D_close_driver();
 
543
 
 
544
    exit(EXIT_SUCCESS);
 
545
}
 
546
 
 
547
static void set_color(char *tcolor)
 
548
{
 
549
    int r, g, b, color;
 
550
 
 
551
    if (sscanf(tcolor, "%d:%d:%d", &r, &g, &b) == 3 ||
 
552
        sscanf(tcolor, "0x%02x%02x%02x", &r, &g, &b) == 3) {
 
553
        if (r >= 0 && r < 256 && g >= 0 && g < 256 && b >= 0 && b < 256) {
 
554
            D_RGB_color(r, g, b);
 
555
        }
 
556
    }
 
557
    else {
 
558
        color = D_translate_color(tcolor);
 
559
        if (!color) {
 
560
            G_warning(_("[%s]: No such color. Use '%s'"), tcolor,
 
561
                      DEFAULT_COLOR);
 
562
            color = D_translate_color(DEFAULT_COLOR);
 
563
        }
 
564
        D_use_color(color);
 
565
    }
 
566
 
 
567
 
 
568
    return;
 
569
}
 
570
 
 
571
static int
 
572
get_coordinates(double *x, double *y, double *east, double *north,
 
573
                struct rectinfo win, char **at, char pixel,
 
574
                char geocoor)
 
575
{
 
576
    double e, n;
 
577
 
 
578
    if (at) {
 
579
        e = atof(at[0]);
 
580
        n = atof(at[1]);
 
581
        if (pixel) {
 
582
            *x = e + win.l;
 
583
            *y = n + win.t;
 
584
            e = D_d_to_u_col(*x);
 
585
            n = D_d_to_u_row(*y);
 
586
        }
 
587
        else if (geocoor) {
 
588
            *x = D_u_to_d_col(e);
 
589
            *y = D_u_to_d_row(n);
 
590
        }
 
591
        else {
 
592
            *x = win.l + (win.r - win.l) * e / 100.0;
 
593
            *y = win.t + (win.b - win.t) * (100.0 - n) / 100.0;
 
594
            e = D_d_to_u_col(*x);
 
595
            n = D_d_to_u_row(*y);
 
596
        }
 
597
    }
 
598
    else
 
599
        return 1;
 
600
 
 
601
    if (east)
 
602
        *east = e;
 
603
    if (north)
 
604
        *north = n;
 
605
 
 
606
    return 0;
 
607
}
 
608
 
 
609
static void draw_text(char *text, double *x, double *y, double size, char *align,
 
610
                      double rotation, char bold, int do_background, int fg_color, int bg_color)
 
611
{
 
612
    double w, h;
 
613
    double t, b, l, r;
 
614
    double c, s;
 
615
    int pt, pb, pl, pr;
 
616
 
 
617
    /* TODO: get text dimension */
 
618
    /* R_get_text_box() does not work with rotation and returns a little bit
 
619
     * bigger dimension than actual text size */
 
620
    if (rotation != 0.0)
 
621
        D_text_rotation(0.0);
 
622
 
 
623
    D_get_text_box(text, &t, &b, &l, &r);
 
624
 
 
625
    if (rotation != 0.0)
 
626
        D_text_rotation(rotation * 180.0 / M_PI);
 
627
    w = r - l;
 
628
    h = b - t;
 
629
    if (w > 0)
 
630
        w += 0.2 * size;
 
631
    else
 
632
        /* D_text() does not draw " ". */
 
633
        w = 0.8 * size;
 
634
    if (h > 0)
 
635
        h += 0.2 * size;
 
636
    else
 
637
        /* D_text() does not draw " ". */
 
638
        h = 0.8 * size;
 
639
 
 
640
    c = cos(rotation);
 
641
    s = sin(rotation);
 
642
 
 
643
    if (strcmp(align, "ll") != 0) {
 
644
        switch (align[0]) {
 
645
        case 'l':
 
646
            break;
 
647
        case 'c':
 
648
            *x += h / 2.0 * s;
 
649
            *y += h / 2.0 * c;
 
650
            break;
 
651
        case 'u':
 
652
            *x += h * s;
 
653
            *y += h * c;
 
654
            break;
 
655
        }
 
656
 
 
657
        switch (align[1]) {
 
658
        case 'l':
 
659
            break;
 
660
        case 'c':
 
661
            *x -= w / 2.0 * c;
 
662
            *y += w / 2.0 * s;
 
663
            break;
 
664
        case 'r':
 
665
            *x -= w * c;
 
666
            *y += w * s;
 
667
            break;
 
668
        }
 
669
    }
 
670
 
 
671
    if (do_background) {
 
672
        pl = *x - size/2; /* some pixels margin for both sides */
 
673
        pt = *y + size/2;
 
674
        pr = *x + w + size/2;
 
675
        pb = *y - h - size/2;
 
676
        D_use_color(bg_color);
 
677
        D_box_abs(pl, pt, pr, pb);    /* draw the box */
 
678
        D_use_color(fg_color); /* restore */
 
679
    }
 
680
 
 
681
    D_pos_abs(*x, *y);
 
682
    D_text(text);
 
683
 
 
684
    if (bold) {
 
685
        D_pos_abs(*x, *y + 1);
 
686
        D_text(text);
 
687
        D_pos_abs(*x + 1, *y);
 
688
        D_text(text);
 
689
    }
 
690
 
 
691
    *x += w * c;
 
692
    *y -= w * s;
 
693
 
 
694
    return;
264
695
}