source: tags/initial/WINDOW/AW_xfig.cxx

Last change on this file was 2, checked in by oldcode, 24 years ago

Initial revision

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 18.1 KB
Line 
1/* -----------------------------------------------------------------
2 * Module:                        WINDOW/AW_xfig.cxx
3 *
4 * Exported Classes:              xfig
5 *
6 * Description: functions for processing xfig graphics for requesters, ...
7 *
8 * Integration Notes:
9 *
10 * 1) cleanup of fopen
11 *
12 * -----------------------------------------------------------------
13 */
14
15/*
16 * $Header$
17 *
18 * $Log$
19 * Revision 1.1  2000/11/23 09:41:17  westram
20 * Initial revision
21 *
22 * Revision 1.8  1995/03/13  16:53:41  jakobi
23 * *** empty log message ***
24 *
25 * Revision 1.7  1995/03/13  15:22:33  jakobi
26 * *** empty log message ***
27 *
28 * Revision 1.7  1995/03/13  15:22:33  jakobi
29 * *** empty log message ***
30 *
31 * Revision 1.6  1995/03/13  12:23:48  jakobi
32 * *** empty log message ***
33 *
34 */
35
36#include <stdio.h>
37#include <stdlib.h>
38#include <memory.h>
39#include <math.h>
40#include <limits.h>
41#include <string.h>
42#include <arbdb.h>              // hash functions
43#include "aw_root.hxx"
44#include "aw_device.hxx"
45#include "aw_xfig.hxx"
46
47
48/* -----------------------------------------------------------------
49 * Function:                     AW_xfig::AW_xfig
50 *
51 * Arguments:                    xfig file, fontsize (>0: abort on error - use for requesters,
52 *                                                    <0: returns NULL on error)
53 *
54 * Returns:                      graphical data or NULL or exit!
55 *
56 * Description:                  load xfig graphical data for construction of requesters,
57 *                               is also used to load line-data of vectorfont
58 *
59 * NOTE:                         
60 *
61 * Dependencies:
62 * -----------------------------------------------------------------
63 */
64
65// --------------------------------------------------------------------------------
66//     inline int scaleAndRound(int unscaled, double scaleFactor)
67// --------------------------------------------------------------------------------
68inline int scaleAndRound(int unscaled, double scaleFactor) {
69    double scaled = double(unscaled)*scaleFactor;
70    return int(scaled);
71    //return scaled>0 ? int(scaled+0.5) : -int(-scaled+0.5);
72}
73
74// --------------------------------------------------------------------------------
75//     class Xfig_Eater
76// --------------------------------------------------------------------------------
77class Xfig_Eater {
78    char *buffer;
79    const char *delim;
80   
81    char *p; // last return of strtok
82    bool failed;
83   
84    void nextToken() {
85        if (!failed) {
86            p = strtok(buffer, delim);
87            buffer = 0;
88            if (!p) failed = true;
89        }
90    }
91   
92public:
93    Xfig_Eater(char *buffer_, const char *delim_) : buffer(buffer_), delim(delim_) {
94        p = 0;
95        failed = false;
96    }
97   
98    bool eat_int(int& what)  {
99        nextToken();
100        if (failed) return false;       
101        what = atoi(p);
102        return true;
103    }
104   
105    bool ignore(unsigned count=1) {
106        while (count-->0) {
107            nextToken();
108            if (failed) return false;
109        }
110        return true;
111    }
112   
113    char *get_rest() {
114        if (failed || !p) return 0;
115        return p+strlen(p)+1;
116    }
117};
118
119// --------------------------------------------------------------------------------
120//     AW_xfig::AW_xfig(const char *filename, int font_size)
121// --------------------------------------------------------------------------------
122AW_xfig::AW_xfig(const char *filename, int font_size)
123{
124    int bail_out=0;
125    const char *error_notice = "unknown";
126    char *ret;
127    char *expanded_filename = 0;
128    enum {
129        XFIG_UNKNOWN,
130        XFIG_OLD_FORMAT, // XFIG 2.1 saves old format
131        XFIG_NEW_FORMAT, // XFIG 3.2 saves new format
132        XFIG_UNSUPPORTED
133       
134    } version = XFIG_UNKNOWN;
135
136    if(!filename || !strlen(filename)) return;
137    memset(this,0,sizeof(AW_xfig));
138    font_scale = abs(font_size) / (float) XFIG_DEFAULT_FONT_SIZE;     
139    dpi_scale = font_scale;
140
141    const char *arbhome = GB_getenvARBHOME();
142    char *buffer = (char *)calloc(sizeof(char),MAX_XFIG_LENGTH);
143
144    FILE *file;
145    if (filename[0]=='/') {
146        // absolute file ?
147        strcpy(buffer,filename);
148        file=fopen(buffer,"r");
149    } else { 
150        // in $ARBHOME/lib/pictures ?
151        sprintf(buffer,"%s/lib/pictures/%s",arbhome,filename);
152        file=fopen(buffer,"r");
153        if (!file) { 
154            // in $ARBHOME ?
155            sprintf(buffer,"%s/%s",arbhome,filename);
156            file = fopen(buffer,"r");
157            if (!file) {
158                                // relative to $CWD?
159                sprintf(buffer,"%s",filename);
160                file = fopen(buffer,"r");
161            }
162        }
163    }
164    if (!file) bail_out=1;
165   
166    expanded_filename = strdup(buffer);
167    int mainVersion = 0;
168    int subVersion = 0;
169    int lineNumber = 0;
170   
171    if (!bail_out) {
172        ret = fgets(buffer,MAX_XFIG_LENGTH,file); ++lineNumber;
173        if (!ret || strncmp("#FIG",ret,4) ) {
174            bail_out=1;
175        }
176        else {
177            char *xfig_version = strchr(ret, ' ');
178            if (!xfig_version) {
179                bail_out = 1;
180            }
181            else {
182                *xfig_version++ = 0;
183                mainVersion = atoi(xfig_version);
184               
185                char *vers_point = strchr(xfig_version, '.');               
186                if (vers_point) {
187                    *vers_point++ = 0;
188                    subVersion = atoi(vers_point);
189                }
190                else {
191                    subVersion = 0; // none
192                }
193               
194                if (mainVersion>3 || (mainVersion==3 && subVersion>2)) {
195                    version = XFIG_UNSUPPORTED; // unsupported (maybe only untested)
196                    error_notice = "Xfig-format above 3.2 not supported";
197                    bail_out = 1;                   
198                }
199                else {
200                    if (mainVersion==3 && subVersion==2) {                       
201                        version = XFIG_NEW_FORMAT;
202                    }
203                    else {
204                        version = XFIG_OLD_FORMAT;
205                    }
206                }               
207            }
208        }
209    }
210       
211    if (!bail_out) {
212        ret = fgets(buffer,MAX_XFIG_LENGTH,file); ++lineNumber;
213        if (!ret ) bail_out=1;
214    }
215   
216    if (bail_out) {
217    do_bail_out:   
218        aw_assert(error_notice);
219        aw_assert(expanded_filename);
220        if (font_size>0) 
221            fprintf(stderr,"Error: Xfig Resource File %s not found or invalid file - programmer's error or defect installation (circumstances: %s)\n",
222                    expanded_filename, error_notice);
223        else {
224            sprintf(AW_ERROR_BUFFER,"Warning: Requested Xfig Resource File %s not found or invalid (circumstances: %s).\n",
225                    expanded_filename, error_notice);
226            aw_message();
227        } 
228       
229        free(expanded_filename);
230        delete buffer;
231        if (file) fclose(file);
232       
233        // exit or return
234        if (font_size>0) exit(-1) ; else return;
235    }
236   
237
238    // failure of the constructor is shown as missing hash/text/lines on return
239       
240    if (font_size<0) font_size = abs(font_size);
241   
242    hash = GBS_create_hash(100,0);
243    maxx = maxy = 0;
244    minx = miny = INT_MAX;
245   
246    if (version==XFIG_NEW_FORMAT) { // XFIG 3.2 format
247        // new xfig format has the following changes:
248        //
249        //  - header (see just below)
250        //  - lines do not end with 9999 9999
251        //  - ??? maybe more changes
252       
253       
254        // over-read xfig-header:
255        // Landscape
256        // Center
257        // Metric
258        // A4     
259        // 100.00
260        // Single
261        // -2
262       
263        int count;
264        for (count = 0;
265             ret && count<=6;
266             ret=fgets(buffer,MAX_XFIG_LENGTH,file), count++,  ++lineNumber)
267        {
268            const char *awaited = 0;
269            switch (count) {
270                case 0: awaited = "Landscape"; break;
271                case 1: awaited = "Center"; break;
272                case 2: awaited = "Metric"; break;
273                case 3: awaited = "A4"; break;
274                case 4: awaited = "100.00"; break;
275                case 5: awaited = "Single"; break;
276                case 6: awaited = "-2"; break;
277                default: aw_assert(0);
278            }
279           
280            if (strncmp(ret, awaited, strlen(awaited))!=0) {
281                error_notice = GBS_global_string("'%s' awaited in line #%i", awaited, lineNumber);           
282                goto do_bail_out;
283            }
284        }
285    }
286   
287    // read resolution
288    int dpi = 80; 
289    int default_dpi = 80; // used in old version (before 3.2)   
290    if (ret) {
291        char *p = strtok(ret, "\t");
292        if (p) dpi = atoi(p);
293       
294        ret = fgets(buffer,MAX_XFIG_LENGTH,file); ++lineNumber;
295       
296        if (dpi!=default_dpi) dpi_scale = font_scale * (double(default_dpi)/double(dpi));
297    }
298   
299    while (ret) {
300        AW_BOOL got_nextline = AW_FALSE;
301        char *p;
302        int width =0;
303        int color = 0;
304        int x,y;
305       
306        if (ret[0]=='2')  { // lines
307            int oldx =0,oldy =0;
308           
309            {
310                Xfig_Eater args(ret, " \t");
311           
312                bool ok =
313                    args.ignore(3) &&       // ignore '2', type, depth
314                    args.eat_int(width) &&  // width
315                    args.eat_int(color);    // color
316               
317                if (!ok) break;
318            }
319           
320            while (1) {
321                ret = fgets(buffer,MAX_XFIG_LENGTH,file);  ++lineNumber;
322                if (!ret) break;
323                if (ret[0]!='\t') {
324                    got_nextline = AW_TRUE;
325                    break;
326                }
327               
328                Xfig_Eater args(ret, " \t");               
329                bool ok = true;               
330                oldx = oldy = INT_MAX;
331               
332                while (ok) {
333                    ok = args.eat_int(x) && args.eat_int(y);
334                    if (!ok) break;
335                   
336                    // 9999/9999 is the end of line-points marker in old version
337                    if (version==XFIG_OLD_FORMAT && x==9999 && y==9999) break; 
338                   
339                    x = scaleAndRound(x, dpi_scale);
340                    y = scaleAndRound(y, dpi_scale);
341                    //                     x = (int)(x*scale);
342                    //                     y = (int)(y*scale);
343
344                    if (x>maxx) maxx = x;
345                    if (y>maxy) maxy = y;
346                    if (x<minx) minx = x;
347                    if (y<miny) miny = y;
348
349                    aw_assert(x>0 && y>0);
350                   
351                    if (oldx == INT_MAX && oldy == INT_MAX) {
352                        oldx = x;
353                        oldy = y;
354                        continue;
355                    }
356                   
357                    struct AW_xfig_line *xline = new AW_xfig_line;                   
358                    if (width>= MAX_LINE_WIDTH) width = MAX_LINE_WIDTH - 1;
359                    xline->next = line[width];
360                    line[width] = xline;
361                    xline->x0 = oldx;
362                    xline->y0 = oldy;
363                    xline->x1 = x;
364                    xline->y1 = y;
365                    oldx = x;
366                    oldy = y;
367                    xline->color = color;               
368                }
369            }
370           
371        } // end if ('2')
372       
373        else if (ret[0]=='4') { // text           
374            int align;
375            int fontnr;
376            int fontsize;
377           
378            // old format: 4 align font  fontsize   depth   color ???       angle justi flags width x y text
379            // new format: 4 align color depth      ???     font  fontsize  angle justi flags width x y text
380            //                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
381           
382            Xfig_Eater args(ret, " \t");
383           
384            bool ok =
385                args.ignore(1) &&       // the '4'               
386                args.eat_int(align);    // align
387           
388            if (ok) {
389                if (version==XFIG_OLD_FORMAT) {
390                    ok = 
391                        args.eat_int(fontnr) &&         // font
392                        args.eat_int(fontsize) &&       // fontsize
393                        args.ignore(1) &&               // depth
394                        args.eat_int(color) &&          // color
395                        args.ignore(1);                 // ???
396                }
397                else {
398                    aw_assert(version==XFIG_NEW_FORMAT);
399                   
400                    ok = 
401                        args.eat_int(color) &&          // color
402                        args.ignore(1) &&               // depth
403                        args.ignore(1) &&               // ???
404                        args.eat_int(fontnr) &&         // font
405                        args.eat_int(fontsize);         // fontsize
406                }
407               
408                if (ok) {
409                    ok = 
410                        args.ignore(3) &&           // angle, justi, flags
411                        args.eat_int(width) &&      // width
412                        args.eat_int(x) &&          // x
413                        args.eat_int(y);            // y
414                   
415                }
416            }
417           
418            if (ok && (p=args.get_rest())!=0) {
419                x = scaleAndRound(x, dpi_scale);
420                y = scaleAndRound(y, dpi_scale);                       
421               
422                while (*p==' ' || *p=='\t') ++p;
423               
424                char *endf = strchr(p, 1); // search for ASCII-1 (new EOL-marker)
425                char *endf2 = GBS_find_string(p, "\\001", 0); // search for "\001" (Pseudo-ASCII-1)
426                if (endf || endf2) {
427                    if (endf) *endf = 0;       
428                    if (endf2) *endf2 = 0;     
429                }
430               
431                if (*p=='$') {          // text starts with a '$'
432                    // place a button
433                    if (!strcmp(p,"$$")) {
434                        this->centerx = x;
435                        this->centery = y;
436                    }else{
437                        struct AW_xfig_pos *xpos = new AW_xfig_pos;
438                        xpos->center = align;
439                        xpos->x = x; xpos->y = y;
440                        GBS_write_hash(hash,p+1,(long)xpos);
441                    }
442                }else{
443                    struct AW_xfig_text *xtext = new AW_xfig_text;
444                    xtext->x = x;
445                    xtext->y = y;
446
447                    if (x>maxx) maxx = x;
448                    if (y>maxy) maxy = y;
449                    if (x<minx) minx = x;
450                    if (y<miny) miny = y;
451
452                    xtext->text = strdup(p);
453                    xtext->fontsize = fontsize;
454                    xtext->color = color;
455                    xtext->center = align;
456                    xtext->font = fontnr;
457                    xtext->next = text;
458                    text = xtext;
459                }               
460            }
461           
462        } // end if ('4')
463       
464        if (!got_nextline) {
465            ret = fgets(buffer,MAX_XFIG_LENGTH,file);  ++lineNumber; 
466        }
467    }   
468   
469    this->size_x = maxx - minx;
470    this->size_y = maxy - miny;
471    delete buffer;
472    free(expanded_filename);
473}
474
475long aw_xfig_hash_free_loop(const char *key,long val)
476{
477    AWUSE(key);
478    if (val) free( (char *)val);
479    return 0;
480}
481
482AW_xfig::~AW_xfig(void)
483{
484    int i;
485
486    if (hash) {
487        GBS_hash_do_loop(hash,(gb_hash_loop_type)aw_xfig_hash_free_loop);
488        GBS_free_hash(hash);
489    }
490    struct AW_xfig_text *xtext;
491    while(text) {
492        xtext = text;
493        text = text->next;
494        delete xtext->text;
495        delete xtext;
496    }
497
498    struct AW_xfig_line *xline;
499    for (i=0;i<MAX_LINE_WIDTH; i++){
500        while(line[i]){
501            xline = line[i];
502            line[i] = xline->next;
503            delete xline;
504        }
505    }
506}
507
508void AW_xfig::print(AW_device *device)
509{
510    int i;
511    AW_rectangle ws;    // window size
512    device->get_area_size(&ws);
513    device->clear();
514    struct AW_xfig_text *xtext;
515    for (xtext = text; xtext; xtext=xtext->next){
516        char *str = xtext->text;
517        int x = xtext->x;
518        int y = xtext->y;
519        if (str[0] == 'Y' && str[1] == ':' ){
520            y += (ws.b - ws.t)- size_y;
521            str += 2;
522        }
523        device->text(xtext->gc,str,(AW_pos)x,(AW_pos)y,(AW_pos)xtext->center*.5,-1,0,0);                // filter
524    }
525
526    struct AW_xfig_line *xline;
527    for (i=0;i<MAX_LINE_WIDTH; i++){
528        device->set_line_attributes(0,(AW_pos)scaleAndRound(i, font_scale),AW_SOLID); 
529        //device->set_line_attributes(0,(AW_pos)i,AW_SOLID);
530        for (xline = line[i]; xline; xline=xline->next){
531            device->line(0,     (AW_pos)xline->x0,(AW_pos)xline->y0,
532                         (AW_pos)xline->x1,(AW_pos)xline->y1,
533                         -1,0,0);                               // filter
534        }
535    }
536}
537
538void AW_xfig::create_gcs(AW_device *device, int depth)
539{
540    GB_HASH *gchash;
541    int gc;
542    char fontstring[100];
543    gchash = GBS_create_hash(100,0);
544
545    struct AW_xfig_text *xtext;
546    gc = 0;
547    device->new_gc( gc ); // create at least one gc ( 0 ) for the lines
548    device->set_foreground_color( gc, AW_WINDOW_FG );
549    if (depth<=1) device->set_function( gc,AW_XOR);
550    device->set_line_attributes( gc, 0.3, AW_SOLID );
551    gc = 1;                     // create gc for texts
552    for (xtext = text; xtext; xtext=xtext->next){
553        sprintf(fontstring,"%i-%i",xtext->font,scaleAndRound(xtext->fontsize, font_scale));
554        //sprintf(fontstring,"%i-%i",xtext->font,(int)(dpi_scale * xtext->fontsize));
555        if ( !(xtext->gc = (int)GBS_read_hash(gchash,fontstring)) ) {           
556            device->new_gc( gc );
557            device->set_line_attributes( gc, 0.3, AW_SOLID );
558            device->set_font( gc, xtext->font, scaleAndRound(xtext->fontsize, font_scale));
559            //device->set_font( gc, xtext->font, (int)(scale * xtext->fontsize) );
560            device->set_foreground_color( gc, AW_WINDOW_FG );
561            if (depth<=1) device->set_function( gc,AW_XOR);
562            xtext->gc = gc;
563            GBS_write_hash(gchash,fontstring,gc);
564            gc++;
565        }
566    }
567    GBS_free_hash(gchash);
568}
Note: See TracBrowser for help on using the repository browser.