~ubuntu-branches/ubuntu/utopic/tcm/utopic

« back to all changes in this revision

Viewing changes to src/ui/figgrafport.c

  • Committer: Bazaar Package Importer
  • Author(s): Otavio Salvador
  • Date: 2003-07-03 20:08:21 UTC
  • Revision ID: james.westby@ubuntu.com-20030703200821-se4xtqx25e5miczi
Tags: upstream-2.20
ImportĀ upstreamĀ versionĀ 2.20

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
////////////////////////////////////////////////////////////////////////////////
 
2
//
 
3
// This file is part of Toolkit for Conceptual Modeling (TCM).
 
4
// (c) copyright 2001, Universiteit Twente.
 
5
// Author: Frank Dehne (frank@cs.vu.nl), David N. Jansen (dnjansen@cs.utwente.nl).
 
6
//
 
7
// TCM is free software; you can redistribute it and/or modify
 
8
// it under the terms of the GNU General Public License as published by
 
9
// the Free Software Foundation; either version 2 of the License, or
 
10
// (at your option) any later version.
 
11
//
 
12
// TCM is distributed in the hope that it will be useful,
 
13
// but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
// GNU General Public License for more details.
 
16
//
 
17
// You should have received a copy of the GNU General Public License
 
18
// along with TCM; if not, write to the Free Software
 
19
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 
20
// 02111-1307, USA.
 
21
////////////////////////////////////////////////////////////////////////////////
 
22
#include "figgrafport.h"
 
23
#include "application.h"
 
24
#include <ctype.h>
 
25
#include <math.h>
 
26
 
 
27
// Factor for X coordinates to Fig coordinates.
 
28
// X display : 1 dot = 1/80 inch
 
29
// X Fig     : 1 dot = 1/1200 inch
 
30
// const double FigGrafport::F = 1200/80;
 
31
// const double FigGrafport::F = 14.4578;
 
32
const double FigGrafport::F = 15;
 
33
#define deg2rad (M_PI / 180.0)
 
34
 
 
35
FigGrafport::FigGrafport(const char *fileName): Grafport() {
 
36
        if (equal(fileName, ""))
 
37
                fd = stdout;
 
38
        else
 
39
                fd = fopen(fileName, "w");
 
40
        succes = (fd != 0);
 
41
        penColor = -1;
 
42
        fillColor = -1;
 
43
        psFont = -1;
 
44
        texFont = 0;
 
45
        texFonts = False;
 
46
        InitColors();
 
47
}
 
48
 
 
49
FigGrafport::~FigGrafport() {
 
50
        if (succes)
 
51
                fclose(fd);
 
52
}
 
53
 
 
54
void FigGrafport::InitColors() {
 
55
        // add standard Xfig colors.
 
56
        // "pixel"-value is misused as xfig color key.
 
57
        AddColor("black", 0);
 
58
        AddColor("blue", 1);
 
59
        AddColor("green", 2);
 
60
        AddColor("cyan", 3);
 
61
        AddColor("red", 4);
 
62
        AddColor("magenta", 5);
 
63
        AddColor("yellow", 6);
 
64
        AddColor("white", 7);
 
65
        // here could come standard colors 8-30 (is not necessary).
 
66
        AddColor("gold", 31);
 
67
 
 
68
        int n = 32; // user defined colors are from 32 till 543.
 
69
        List<Color *> *appColors = theApplication->GetColors();
 
70
        for (appColors->first(); !appColors->done(); appColors->next()) {
 
71
                // define other colors as user defined colors.
 
72
                if (!LookupColor(&appColors->cur()->name)) {
 
73
                        Color *color = new Color(*appColors->cur());
 
74
                        color->pixel = n; 
 
75
                        color->allocated = True;
 
76
                        GetColors()->add(color);
 
77
                        n++;
 
78
                        if (n > 543) {
 
79
                                error("%s, line %d: "
 
80
                                      "too many user defined colors"
 
81
                                        __FILE__, __LINE__);
 
82
                                break;
 
83
                        }
 
84
                }
 
85
 
 
86
        }
 
87
}
 
88
 
 
89
void FigGrafport::SetBackgroundColor(const char *c) {
 
90
        string s = c;
 
91
        SetBackgroundColor(&s);
 
92
}
 
93
 
 
94
void FigGrafport::SetForegroundColor(const char *c) {
 
95
        string s = c;
 
96
        SetForegroundColor(&s);
 
97
}
 
98
 
 
99
void FigGrafport::SetBackgroundColor(const string *c) {
 
100
        if (*GetBackgroundColor() == *c)
 
101
                return;
 
102
        Grafport::SetBackgroundColor(c);
 
103
}
 
104
 
 
105
void FigGrafport::SetForegroundColor(const string *c) {
 
106
        if (*GetForegroundColor() == *c)
 
107
                return;
 
108
        Grafport::SetForegroundColor(c);
 
109
        Color *color = LookupColor(c);
 
110
        if (color)
 
111
                penColor = (int)color->pixel;
 
112
        else
 
113
                penColor = -1; // default.
 
114
}
 
115
 
 
116
void FigGrafport::Header(bool landscape) {
 
117
        fprintf(fd, "#FIG 3.1\n");
 
118
        if (landscape)
 
119
                fprintf(fd, "Landscape\n");
 
120
        else
 
121
                fprintf(fd, "Portrait\n");
 
122
        fprintf(fd, "Center\n");
 
123
        fprintf(fd, "Inches\n");
 
124
        fprintf(fd, "1200 2\n");
 
125
 
 
126
        // write user defined colors.
 
127
        int object_code = 0; // color pseudo object code.
 
128
        List<Color *> *c = GetColors();
 
129
        for (c->first(); !c->done(); c->next()) {
 
130
                Color *color = c->cur();
 
131
                if (color->pixel >= 32) {
 
132
                        int r= int(255*color->red);
 
133
                        int g= int(255*color->green);
 
134
                        int b= int(255*color->blue);
 
135
                        fprintf(fd, "%d %d #", object_code, (int)color->pixel);
 
136
                        fprintf(fd, "%.2x%.2x%.2x\n", r, g, b);
 
137
                }
 
138
        }
 
139
}
 
140
 
 
141
void FigGrafport::SetLineWidth(unsigned int w) {
 
142
        if (w == GetLineWidth())
 
143
                return;
 
144
        Grafport::SetLineWidth(w);
 
145
}
 
146
 
 
147
void FigGrafport::SetFont(XFont *f) {
 
148
        Grafport::SetFont(f);
 
149
        SetPSFont();
 
150
        SetTexFont();
 
151
}
 
152
 
 
153
void FigGrafport::DrawFigEllipse(double center_x, double center_y,
 
154
        double radius_x, double radius_y, int sub_type)
 
155
{
 
156
        int object_code = 1;  // Ellipse
 
157
 
 
158
        int line_style = 0;  // Solid
 
159
        if (GetLineStyle()==LineStyle::DASHED)
 
160
                line_style = 1;
 
161
        if (GetLineStyle()==LineStyle::DOTTED ||
 
162
            GetLineStyle()==LineStyle::WIDE_DOTTED)
 
163
                line_style = 2;
 
164
 
 
165
        int thickness = GetLineWidth();  // 1/80 inch
 
166
        if (GetLineStyle()==LineStyle::INVISIBLE &&
 
167
            GetFillStyle()==FillStyle::UNFILLED)
 
168
                return; // don't draw
 
169
 
 
170
        int pen_color = penColor;
 
171
        int fill_color = 7; // 7 = white
 
172
        int depth = 0;
 
173
        int pen_style = 0;  // not used.
 
174
        int area_fill = -1; // no fill.
 
175
        if (GetFillStyle()==FillStyle::FILLED) {
 
176
                fill_color = fillColor;
 
177
                area_fill = 20;// full saturation.
 
178
                if (GetLineStyle()==LineStyle::INVISIBLE)
 
179
                        pen_color = fill_color;
 
180
        } 
 
181
 
 
182
        float style_val = 0;// 1/80 inch
 
183
        if (GetLineStyle()==LineStyle::DASHED)
 
184
                style_val = 4.0;
 
185
        if (GetLineStyle()==LineStyle::DOTTED)
 
186
                style_val = 1.0;
 
187
        if (GetLineStyle()==LineStyle::WIDE_DOTTED)
 
188
                style_val = 2.0;
 
189
 
 
190
        int direction = 1; // always 1
 
191
        float angle = 0;   // angle with x-axis.
 
192
        double start_x = center_x;
 
193
        double start_y = center_y;
 
194
        double end_x = start_x + radius_x;
 
195
        double end_y = start_y + radius_y;
 
196
 
 
197
        fprintf(fd, "%d %d %d %d %d %d %d %d %d ", object_code, sub_type,
 
198
                line_style, thickness, pen_color, fill_color, depth,
 
199
                pen_style, area_fill);
 
200
        fprintf(fd, "%f %d %f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f\n",
 
201
                style_val, direction, angle, center_x, center_y, radius_x,
 
202
                radius_y, start_x, start_y, end_x, end_y);
 
203
}
 
204
 
 
205
 
 
206
void FigGrafport::DrawFigPolyLine(List<DPoint *> *points,
 
207
                                  int sub_type, double radius) {
 
208
        int object_code = 2; // Polyline
 
209
 
 
210
        int line_style = 0;  // Solid
 
211
        if (GetLineStyle()==LineStyle::DASHED)
 
212
                line_style = 1;
 
213
        if (GetLineStyle()==LineStyle::DOTTED ||
 
214
            GetLineStyle()==LineStyle::WIDE_DOTTED)
 
215
                line_style = 2;
 
216
 
 
217
        int thickness = GetLineWidth();  // 1/80 inch
 
218
        if (GetLineStyle()==LineStyle::INVISIBLE &&
 
219
            GetFillStyle()==FillStyle::UNFILLED)
 
220
                return;
 
221
                // thickness = 0;
 
222
 
 
223
        int pen_color = penColor;
 
224
        int fill_color = 7; // 7 = white
 
225
        int depth = 0;
 
226
        int pen_style = 0;  // not used.
 
227
        int area_fill = -1; // no fill.
 
228
        if (GetFillStyle()==FillStyle::FILLED) {
 
229
                fill_color = fillColor;
 
230
                area_fill = 20;// full saturation.
 
231
                if (GetLineStyle()==LineStyle::INVISIBLE)
 
232
                        pen_color = fill_color;
 
233
        }
 
234
 
 
235
        float style_val = 0;// 1/80 inch
 
236
        if (GetLineStyle()==LineStyle::DASHED)
 
237
                style_val = 4.0;
 
238
        if (GetLineStyle()==LineStyle::DOTTED)
 
239
                style_val = 1.0;
 
240
        if (GetLineStyle()==LineStyle::WIDE_DOTTED)
 
241
                style_val = 2.0;
 
242
 
 
243
        int join_style = 0; // Miter
 
244
        int cap_style = 0;  // Butt
 
245
        int forward_arrow = 0;
 
246
        int backward_arrow = 0;
 
247
        int npoints = points->count();
 
248
 
 
249
        fprintf(fd, "%d %d %d %d %d %d %d %d %d %.1f %d %d %.0f %d %d %d\n",
 
250
                object_code, sub_type, line_style, thickness, pen_color,
 
251
                fill_color, depth, pen_style, area_fill, style_val,
 
252
                join_style, cap_style, radius, forward_arrow, backward_arrow,
 
253
                npoints);
 
254
        for (points->first(); !points->done(); points->next()) {
 
255
                DPoint *pt = points->cur();
 
256
                fprintf(fd, "%.0f %.0f ", pt->x, pt->y);
 
257
        }
 
258
        fprintf(fd, "\n"); 
 
259
}
 
260
 
 
261
void FigGrafport::DrawFigRectangle(double _x, double _y, double _wd, double _ht,
 
262
                                   int sub_type, double radius) {
 
263
        double x = Zoom(_x); 
 
264
        double y = Zoom(_y);
 
265
        double wd = Zoom(_wd);
 
266
        double ht = Zoom(_ht);
 
267
 
 
268
        List<DPoint *> points;
 
269
 
 
270
        double xl = x*F;
 
271
        double yt = y*F;
 
272
        double xr = (x+wd)*F;
 
273
        double yb = (y+ht)*F;
 
274
        DPoint p1(xl, yt);
 
275
        DPoint p2(xl, yb);
 
276
        DPoint p3(xr, yb);
 
277
        DPoint p4(xr, yt);
 
278
        points.add(&p1);
 
279
        points.add(&p2);
 
280
        points.add(&p3);
 
281
        points.add(&p4);
 
282
        points.add(&p1);
 
283
 
 
284
        DrawFigPolyLine(&points, sub_type, radius);
 
285
 
 
286
        if (GetLineStyle()==LineStyle::DUAL) {
 
287
                SetLineStyle(LineStyle::SOLID); // avoid recursion
 
288
                int n = 2*GetLineWidth();
 
289
                if (_ht > 2*n && _wd > 2*n)
 
290
                        DrawFigRectangle(_x+n, _y+n, _wd-2*n, _ht-2*n, 
 
291
                                sub_type, radius);
 
292
                SetLineStyle(LineStyle::DUAL);
 
293
        }
 
294
}
 
295
 
 
296
void FigGrafport::DrawRectangle(double x, double y, double wd, double ht) {
 
297
        DrawFigRectangle(x, y, wd, ht, 2);
 
298
        SetFillStyle(FillStyle::UNFILLED);
 
299
}
 
300
 
 
301
void FigGrafport::DrawUnzoomedRectangle(double x, double y, double wd, double ht) {
 
302
        DrawFigRectangle(ZoomCorrect(x), ZoomCorrect(y),
 
303
                      ZoomCorrect(wd), ZoomCorrect(ht), 2);
 
304
}
 
305
 
 
306
void FigGrafport::FillRectangle(double, double, double, double) {
 
307
        SetFillStyle(FillStyle::FILLED);
 
308
        SetFillColor();
 
309
}
 
310
 
 
311
//void FigGrafport::DrawRoundedRectangle(double x, double y, double wd, double ht, double rd) {
 
312
//      DrawFigRectangle(x, y, wd, ht, 4, rd);
 
313
//      SetFillStyle(FillStyle::UNFILLED);
 
314
//}
 
315
//
 
316
//void FigGrafport::FillRoundedRectangle(double, double, double, double, double) {
 
317
//      SetFillStyle(FillStyle::FILLED);
 
318
//      SetFillColor();
 
319
//}
 
320
//
 
321
//void FigGrafport::DrawEllipsedRectangle(double x, double y, double wd, double ht, double rd) {
 
322
//      DrawRoundedRectangle(x, y, wd, ht, rd);
 
323
//}
 
324
//
 
325
//void FigGrafport::FillEllipsedRectangle(double, double, double, double, double) {
 
326
//      SetFillStyle(FillStyle::FILLED);
 
327
//      SetFillColor();
 
328
//}
 
329
//
 
330
//void FigGrafport::DrawDisk(double x, double y, double wd, double ht, double el) {
 
331
//      // draw two lines (without the corner points).
 
332
//        double ah = el/2;
 
333
//        DrawLine(x, y+ah+1, x, y+ht-ah-1);
 
334
//        DrawLine(x+wd, y+ah+1, x+wd, y+ht-ah-1);
 
335
//        // draw 1st ellipse.
 
336
//        DrawEllipse(x, y, wd, el+1);
 
337
//        // draw bottom arc (in two parts)
 
338
//      DrawArc(x, y + ht - el - 1, wd, el + 1, 180, 270);
 
339
//      DrawArc(x, y + ht - el - 1, wd, el + 1, 270, 360);
 
340
//}
 
341
//
 
342
//void FigGrafport::FillDisk(double, double, double, double, double) {
 
343
//      SetFillStyle(FillStyle::FILLED);
 
344
//      SetFillColor();
 
345
//}
 
346
 
 
347
void FigGrafport::DrawFigText(double px, double py, const char *str, int sub_type) {
 
348
        px = Zoom(px);
 
349
        py = Zoom(py);
 
350
        int object_code = 4;  // Text
 
351
        int color = penColor;
 
352
        int depth = 0;
 
353
        int pen_style = 0;  // not used.
 
354
        int figfont;
 
355
        if (texFonts)
 
356
                figfont = texFont; // generate LaTeX fonts.
 
357
        else
 
358
                figfont = psFont;  // generate PostScript fonts.
 
359
        float font_size = GetFont()->GetSize() - 0.1; // possibly some 
 
360
        float angle = 0;            // problems with 'autoresize'.
 
361
        int font_flags;
 
362
        if (texFonts)
 
363
                font_flags = 2;
 
364
        else
 
365
                font_flags = 4;
 
366
        double theight, tlength;
 
367
        GetFigStringSize(str, theight, tlength);
 
368
        double x, y;
 
369
        if (sub_type == 0) {      // lower left (was topleft)
 
370
                x = F*px;
 
371
                y = F*py;
 
372
        }
 
373
        else if (sub_type == 1) { // lower center (was center)
 
374
                x = F*px;
 
375
                y = F*py + theight/2;
 
376
        }
 
377
        else {                   // lower right (was topright)
 
378
                x = F*px;
 
379
                y = F*py;
 
380
        }
 
381
        string theString = str;
 
382
        MakeFigString(&theString);
 
383
        fprintf(fd, "%d %d %d %d %d %d %f %f %d %f %f %.0f %.0f %s\n",
 
384
                object_code, sub_type, color, depth, pen_style,
 
385
                figfont, font_size, angle, font_flags, theight,
 
386
                tlength, x, y, theString.getstr());
 
387
}
 
388
 
 
389
void FigGrafport::DrawStringLeft(double x, double y, const char *str) {
 
390
        DrawFigText(x, y, str, 0);
 
391
}
 
392
 
 
393
void FigGrafport::DrawUnzoomedStringLeft(double x, double y, const char *str) {
 
394
        DrawStringLeft(ZoomCorrect(x), ZoomCorrect(y), str);
 
395
}
 
396
 
 
397
void FigGrafport::DrawStringRight(double x, double y, const char *str) {
 
398
        DrawFigText(x, y, str, 2);
 
399
}
 
400
 
 
401
void FigGrafport::DrawStringCentered(double x, double y, const char *str) {
 
402
        DrawFigText(x, y, str, 1);
 
403
}
 
404
 
 
405
void FigGrafport::DrawUnzoomedStringCentered(double x, double y, const char *str) {
 
406
        DrawStringCentered(ZoomCorrect(x), ZoomCorrect(y), str);
 
407
}
 
408
 
 
409
// Underlined Strings
 
410
void FigGrafport::DrawStringRightUnderlined(double x, double y, const char *str) {
 
411
        DrawStringRight(x, y, str);
 
412
        int wd = GetFont()->StringWidth(str);
 
413
        // DrawStringRight... : 
 
414
        // Corrected Height for y ( == topRighty + GetAscent()) 
 
415
        int cht = GetFont()->GetHeight() - GetFont()->GetAscent();
 
416
        LineStyle::Type save = GetLineStyle();  // save
 
417
        SetLineStyle(LineStyle::SOLID);         // set underline linestyle SOLID
 
418
        DrawLine(x-wd, y+cht, x, y+cht);
 
419
        SetLineStyle(save);                     // and restore
 
420
}
 
421
 
 
422
void FigGrafport::DrawStringLeftUnderlined(double x, double y, const char *str) {
 
423
        DrawStringLeft(x, y, str);
 
424
        int wd = GetFont()->StringWidth(str);
 
425
        // DrawStringLeft... : 
 
426
        // Corrected Height for y ( == topLefty + GetAscent()) 
 
427
        int cht = GetFont()->GetHeight() - GetFont()->GetAscent();
 
428
        LineStyle::Type save = GetLineStyle();  // save
 
429
        SetLineStyle(LineStyle::SOLID);         // set underline linestyle SOLID
 
430
        DrawLine(x, y+cht, x+wd, y+cht);
 
431
        SetLineStyle(save);                     // and restore
 
432
}
 
433
 
 
434
void FigGrafport::DrawStringCenteredUnderlined(double x, double y, const char *str) {
 
435
        DrawStringCentered(x, y, str);
 
436
        int wd = GetFont()->StringWidth(str);
 
437
        int ht = GetFont()->GetHeight();
 
438
        LineStyle::Type save = GetLineStyle();  // save
 
439
        SetLineStyle(LineStyle::SOLID);         // set underline linestyle SOLID
 
440
        DrawLine(x-wd/2, y+ht/2, x+wd/2, y+ht/2);
 
441
        SetLineStyle(save);                     // and restore
 
442
}
 
443
 
 
444
//void FigGrafport::DrawLine(double _x1, double _y1, double _x2, double _y2) {
 
445
//      if (_x1 == _x2 && _y1 == _y2)
 
446
//              return;
 
447
//
 
448
//      double x1 = Zoom(_x1); 
 
449
//      double y1 = Zoom(_y1);
 
450
//      double x2 = Zoom(_x2);
 
451
//      double y2 = Zoom(_y2);
 
452
//
 
453
//      List<DPoint *> points;
 
454
//      int sub_type = 1;
 
455
//
 
456
//      DPoint p1(F*x1, F*y1);
 
457
//      DPoint p2(F*x2, F*y2);
 
458
//      points.add(&p1);
 
459
//      points.add(&p2);
 
460
//
 
461
//      DrawFigPolyLine(&points, sub_type);
 
462
//
 
463
//      if (GetLineStyle()==LineStyle::DUAL) {
 
464
//              SetLineStyle(LineStyle::SOLID);
 
465
//              int n = GetLineWidth();
 
466
//              if (y1 == y2) {  // horizontal
 
467
//                      DrawLine(_x1, _y1+n, _x2, _y2+n);
 
468
//                      DrawLine(_x1, _y1-n, _x2, _y2-n);
 
469
//              }
 
470
//              else if (x1 == x2) {  // vertical
 
471
//                      DrawLine(_x1+n, _y1, _x2+n, _y2);
 
472
//                      DrawLine(_x1-n, _y1, _x2-n, _y2);
 
473
//              }
 
474
//              else {
 
475
//                      DrawLine(_x1, _y1, _x2, _y2);
 
476
//                      DrawLine(_x1, _y1+2*n, _x2, _y2+2*n);
 
477
//              }
 
478
//              SetLineStyle(LineStyle::DUAL);
 
479
//      }
 
480
//      SetFillStyle(FillStyle::UNFILLED);
 
481
//}
 
482
 
 
483
 
 
484
void FigGrafport::DrawUnzoomedLine(double x1, double y1, double x2, double y2) {
 
485
        DrawLine(ZoomCorrect(x1), ZoomCorrect(y1), 
 
486
                 ZoomCorrect(x2), ZoomCorrect(y2));
 
487
}
 
488
 
 
489
 
 
490
//void FigGrafport::DrawCurve(const Point *p1, const Point *p2, 
 
491
//                         const Point *p3, const Point *p4) {
 
492
//      int object_code = 3;  // Spline
 
493
//      int sub_type = 0;     // Open Aproximated Spline
 
494
//
 
495
//      double x1 = Zoom(p1->x*F);
 
496
//      double y1 = Zoom(p1->y*F);
 
497
//      double x2 = Zoom(p2->x*F);
 
498
//      double y2 = Zoom(p2->y*F);
 
499
//      double x3 = Zoom(p3->x*F);
 
500
//      double y3 = Zoom(p3->y*F);
 
501
//      double x4 = Zoom(p4->x*F);
 
502
//      double y4 = Zoom(p4->y*F);
 
503
//
 
504
//      int line_style = 0;  // Solid
 
505
//      if (GetLineStyle()==LineStyle::DASHED)
 
506
//              line_style = 1;
 
507
//      if (GetLineStyle()==LineStyle::DOTTED ||
 
508
//          GetLineStyle()==LineStyle::WIDE_DOTTED)
 
509
//              line_style = 2;
 
510
//
 
511
//      int thickness = GetLineWidth();  // 1/80 inch
 
512
//      if (GetLineStyle()==LineStyle::INVISIBLE)
 
513
//              return;
 
514
//              // thickness = 0;
 
515
//
 
516
//      int pen_color = penColor;
 
517
//      int fill_color = 7; // 7 = white
 
518
//      int depth = 0;
 
519
//      int pen_style = 0;  // not used.
 
520
//      int area_fill = -1; // no fill.
 
521
//      if (GetFillStyle()==FillStyle::FILLED) {
 
522
//              fill_color = fillColor;
 
523
//              area_fill = 20;// full saturation.
 
524
//      } 
 
525
//
 
526
//      float style_val = 0;// 1/80 inch
 
527
//      if (GetLineStyle()==LineStyle::DASHED)
 
528
//              style_val = 4.0;
 
529
//      if (GetLineStyle()==LineStyle::DOTTED)
 
530
//              style_val = 1.0;
 
531
//      if (GetLineStyle()==LineStyle::WIDE_DOTTED)
 
532
//              style_val = 2.0;
 
533
//
 
534
//      int cap_style = 0;  // Butt
 
535
//      int forward_arrow = 0;
 
536
//      int backward_arrow = 0;
 
537
//      int npoints = 4;
 
538
//
 
539
//      fprintf(fd, "%d %d %d %d %d %d %d %d %d %.1f %d %d %d %d\n",
 
540
//              object_code, sub_type, line_style, thickness, pen_color,
 
541
//              fill_color, depth, pen_style, area_fill, style_val,
 
542
//              cap_style, forward_arrow, backward_arrow,
 
543
//              npoints);
 
544
//      fprintf(fd, "%f %f %f %f %f %f %f %f\n",
 
545
//              x1, y1, x2, y2, x3, y3, x4, y4);
 
546
//      SetFillStyle(FillStyle::UNFILLED);
 
547
//}
 
548
 
 
549
 
 
550
void FigGrafport::FillCurve(const DPoint *p) {
 
551
        // 3 = object code: spline, 0 = subtype: open approximated, 0 = line
 
552
        // style: solid, 0 = thickness, 0 = pen color: default, 50 = depth, 0 =
 
553
        // pen style (not used), 20 = area fill: filled, 0.0 = style val: no
 
554
        // dots, 0 = cap style: butt, 0 = forward arrow: none, 0 = backward
 
555
        // arrow: none, 4 = # of points
 
556
        fprintf(fd, "3 0 0 0 0 %d 50 0 20 0.0 0 0 0 4\n", penColor);
 
557
        fprintf(fd, "%.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f\n",
 
558
                Zoom(p[0].x * F), Zoom(p[0].y * F),
 
559
                Zoom(p[1].x * F), Zoom(p[1].y * F),
 
560
                Zoom(p[2].x * F), Zoom(p[2].y * F),
 
561
                Zoom(p[3].x * F), Zoom(p[3].y * F));
 
562
}
 
563
 
 
564
 
 
565
void FigGrafport::DrawSimpleCurve(const DPoint *p) {
 
566
        int line_style;
 
567
        double style_val;
 
568
        switch ( GetLineStyle() ) {
 
569
        case LineStyle::INVISIBLE:
 
570
                return;
 
571
        case LineStyle::DASHED:
 
572
                line_style = 1;
 
573
                style_val = 4.0;
 
574
                break;
 
575
        case LineStyle::DOTTED:
 
576
                line_style = 2;
 
577
                style_val = 1.0;
 
578
                break;
 
579
        case LineStyle::WIDE_DOTTED:
 
580
                line_style = 2;
 
581
                style_val = 2.0;
 
582
                break;
 
583
        default:
 
584
                line_style = 0;
 
585
                style_val = 0.0;
 
586
                break;
 
587
        }
 
588
        // 3 = object code: spline, 0 = subtype: open approximated, 7 = fill
 
589
        // color: white, 0 = depth, 0 = pen style (not used), -1 = area fill:
 
590
        // not filled, 0 = cap style: butt, 0 = forward arrow: none, 0 =
 
591
        // backward arrow: none, 4 = # of points.
 
592
        fprintf(fd, "3 0 %d %d %d 7 0 0 -1 %.1f 0 0 0 4\n",
 
593
                line_style, GetLineWidth(), penColor, style_val);
 
594
        fprintf(fd, "%.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f\n",
 
595
                Zoom(p[0].x * F), Zoom(p[0].y * F),
 
596
                Zoom(p[1].x * F), Zoom(p[1].y * F),
 
597
                Zoom(p[2].x * F), Zoom(p[2].y * F),
 
598
                Zoom(p[3].x * F), Zoom(p[3].y * F));
 
599
}
 
600
 
 
601
 
 
602
void FigGrafport::DrawPoint(double, double) { 
 
603
        // no single points in Xfig
 
604
}
 
605
 
 
606
 
 
607
static void CalcCurvePoints(DPoint *p, double x, double y,
 
608
        double wd, double ht, int a1)
 
609
{
 
610
        /* calculate points for a spline approximating a
 
611
           quarter of an ellipse. */
 
612
        wd *= 0.5;
 
613
        x += wd;
 
614
        ht *= 0.5;
 
615
        y += ht;
 
616
        switch ( a1 ) {
 
617
        case 0:
 
618
                ht = -ht;
 
619
                break;
 
620
        case 90:
 
621
                ht = -ht;
 
622
        case 180:
 
623
                wd = -wd;
 
624
                break;
 
625
        }
 
626
        p[0].Set(x + wd, y);
 
627
#define Factor 1
 
628
// 1 is an estimation, not based on any algorithm...
 
629
// 4.0/3 = Bļæ½zier approximation, but this is too large for B-splines.
 
630
        p[1].Set(x + wd, y + ht * ((M_SQRT2 - 1.0) * Factor));
 
631
        p[2].Set(x + wd * ((M_SQRT2 - 1.0) * Factor), y + ht);
 
632
        p[3].Set(x, y + ht);
 
633
}
 
634
 
 
635
 
 
636
void FigGrafport::DrawSimpleArc(double x, double y,
 
637
        double wd, double ht, int a1, int a2)
 
638
{
 
639
        if ( ! (int) (F * Zoom(wd - ht) + 0.5) ) {
 
640
                /* (almost) circular arc */
 
641
                int line_style;
 
642
                double style_val;
 
643
                switch ( GetLineStyle() ) {
 
644
                case LineStyle::INVISIBLE:
 
645
                        return;
 
646
                case LineStyle::DASHED:
 
647
                        line_style = 1;
 
648
                        style_val = 4.0;
 
649
                        break;
 
650
                case LineStyle::DOTTED:
 
651
                        line_style = 2;
 
652
                        style_val = 1.0;
 
653
                        break;
 
654
                case LineStyle::WIDE_DOTTED:
 
655
                        line_style = 2;
 
656
                        style_val = 2.0;
 
657
                        break;
 
658
                default:
 
659
                        line_style = 0;
 
660
                        style_val = 0.0;
 
661
                        break;
 
662
                }
 
663
                double radius = Zoom((wd + ht) * (F / 4.0));
 
664
                DPoint centre(Zoom(x + wd * 0.5) * F,
 
665
                        Zoom(y + ht * 0.5) * F);
 
666
                // 5 = object code: arc, 1 = subtype: open, 7 = fill colour:
 
667
                // white, 0 = depth, 0 = pn style (not used), -1 = area fill:
 
668
                // not filled, 0 = cap style: butt, 1 = ???,
 
669
                // 0 = forward arrow: none, 0 = backward arrow: none
 
670
                fprintf(fd, "5 1 %d %d %d 7 0 0 -1 %.1f 0 1 0 0",
 
671
                        line_style, GetLineWidth(), penColor,
 
672
                        style_val);
 
673
                fprintf(fd, " %f %f", centre.x, centre.y);
 
674
                double arc1 = a1 * deg2rad;
 
675
                fprintf(fd, " %.0f %.0f", centre.x + radius * cos(arc1),
 
676
                                         centre.y - radius * sin(arc1));
 
677
                double arc3 = (deg2rad / 2.0) * (a1 + a2);
 
678
                fprintf(fd, " %.0f %.0f", centre.x + radius * cos(arc3),
 
679
                                         centre.y - radius * sin(arc3));
 
680
                double arc2 = a2 * deg2rad;
 
681
                fprintf(fd, " %.0f %.0f\n", centre.x+radius * cos(arc2),
 
682
                                         centre.y - radius * sin(arc2));
 
683
        } else {
 
684
                /* elliptic arc: approximate by a curve */
 
685
                DPoint p[4];
 
686
                CalcCurvePoints(p, x, y, wd, ht, a1);
 
687
                DrawSimpleCurve(p);
 
688
        }
 
689
}
 
690
 
 
691
 
 
692
void FigGrafport::FillSegment(double x, double y, double wd, double ht,
 
693
        int a1, int a2)
 
694
{
 
695
        if ( ! (int) (F * Zoom(wd - ht) + 0.5) ) {
 
696
                /* (almost) circular arc */
 
697
                double radius = Zoom((wd + ht) * (F / 4.0));
 
698
                DPoint centre(Zoom(x + wd * 0.5) * F,
 
699
                        Zoom(y + ht * 0.5) * F);
 
700
                // 5 = object code: arc, 1 = subtype: open, 0 = line style:
 
701
                // solid, 0 = line width, 0 = pen color: default, 50 = depth,
 
702
                // 0 = pen style (not used), 20 = area fill: filled, 0.0 =
 
703
                // style value: no dots, 0 = cap style: butt, 1 = ???,
 
704
                // 0 = forward arrow: none, 0 = backward arrow: none
 
705
                fprintf(fd, "5 1 0 0 0 %d 50 0 20 0.0 0 1 0 0",
 
706
                        penColor);
 
707
                fprintf(fd, " %f %f", centre.x, centre.y);
 
708
                double arc1 = a1 * deg2rad;
 
709
                fprintf(fd, " %.0f %.0f", centre.x + radius * cos(arc1),
 
710
                                         centre.y - radius * sin(arc1));
 
711
                double arc3 = (deg2rad / 2.0) * (a1 + a2);
 
712
                fprintf(fd, " %.0f %.0f", centre.x + radius * cos(arc3),
 
713
                                         centre.y - radius * sin(arc3));
 
714
                double arc2 = a2 * deg2rad;
 
715
                fprintf(fd, " %.0f %.0f\n", centre.x+radius * cos(arc2),
 
716
                                         centre.y - radius * sin(arc2));
 
717
        } else {
 
718
                /* elliptic arc: approximate by a curve */
 
719
                DPoint p[4];
 
720
                CalcCurvePoints(p, x, y, wd, ht, a1);
 
721
                FillCurve(p);
 
722
        }
 
723
}
 
724
 
 
725
 
 
726
//void FigGrafport::FillArc(double, double, double, double, int, int) {
 
727
//      /* Actually, this procedure is not implemented correctly; arcs
 
728
//         are never filled as pie slices, but always as segments. dj */
 
729
//      SetFillStyle(FillStyle::FILLED);
 
730
//      SetFillColor();
 
731
//}
 
732
 
 
733
void FigGrafport::DrawEllipse(double x, double y, double wd, double ht) {
 
734
        int sub_type;
 
735
        if (wd == ht)
 
736
                sub_type = 3; // circle def. by radius.
 
737
        else
 
738
                sub_type = 1; // ellipse def. by radius.
 
739
        double radius_x = (wd*F)/2;
 
740
        double radius_y = (ht*F)/2;
 
741
        double center_x = x*F + radius_x;
 
742
        double center_y = y*F + radius_y;
 
743
        DrawFigEllipse(center_x, center_y, radius_x, radius_y, sub_type);
 
744
        if (GetLineStyle()==LineStyle::DUAL) {
 
745
                SetLineStyle(LineStyle::SOLID); // avoid recursion
 
746
                int n = 2*GetLineWidth();
 
747
                if (ht > 2*n && wd > 2*n)
 
748
                        DrawEllipse(x+n, y+n, wd-2*n, ht-2*n);
 
749
                SetLineStyle(LineStyle::DUAL);
 
750
        }
 
751
        SetFillStyle(FillStyle::UNFILLED);
 
752
}
 
753
 
 
754
void FigGrafport::FillEllipse(double, double, double, double) {
 
755
        SetFillStyle(FillStyle::FILLED);
 
756
        SetFillColor();
 
757
}
 
758
 
 
759
void FigGrafport::DrawPolygon(const Point *p, int n) {
 
760
        if (n < 1)
 
761
                return;
 
762
        List<DPoint *> points;
 
763
        int sub_type = 3;
 
764
 
 
765
        for (int i=0; i<n; i++) {
 
766
                double x = F*Zoom(p[i].x);
 
767
                double y = F*Zoom(p[i].y);
 
768
                DPoint *pt = new DPoint(x, y);
 
769
                points.add(pt);
 
770
        }
 
771
        DPoint *pt = new DPoint(F*Zoom(p[0].x), F*Zoom(p[0].y));
 
772
        points.add(pt);
 
773
 
 
774
        DrawFigPolyLine(&points, sub_type);
 
775
        if (GetLineStyle()==LineStyle::DUAL) {
 
776
                int w = 2*GetLineWidth();
 
777
                Point *oldPoints = new Point[n];
 
778
                Point *newPoints = new Point[n];
 
779
                for (int j=0; j<n; j++)
 
780
                        oldPoints[j] = *points[j];
 
781
                RecalcPolygon(oldPoints, n, newPoints, w);
 
782
                List<DPoint *> nPoints;
 
783
                for (int k=0; k<n; k++)
 
784
                        nPoints.add(new DPoint(newPoints[k]));
 
785
                DrawFigPolyLine(&nPoints, sub_type);
 
786
                delete [/* n */] newPoints;
 
787
                delete [/* n */] oldPoints;
 
788
                nPoints.clear();
 
789
        }
 
790
        points.clear();
 
791
        SetFillStyle(FillStyle::UNFILLED);
 
792
}
 
793
 
 
794
void FigGrafport::FillPolygon(const Point *p, int n) {
 
795
        if ( n < 2 )
 
796
                return;
 
797
        DPoint *plist = new DPoint [n];
 
798
        for ( int i = n ; i-- ; )
 
799
                plist[i] = p[i];
 
800
        FillPolygon(plist, n);
 
801
}
 
802
 
 
803
 
 
804
void FigGrafport::FillPolygon(const DPoint *p, int n) {
 
805
        if (n < 2)
 
806
                return;
 
807
        if ( p[0] == p[n - 1] )
 
808
                n--;
 
809
        // 2 = type: polyline, 1 = subtype: open, 0 = line style: solid, 0 =
 
810
        // line width, -1 = pen colour: default, 50 = depth, 0 = pen style
 
811
        // (not used), 20 = area fill: filled, 0.0 = style val: no dots, 0 =
 
812
        // join style: miter, 0 = cap style: butt, -1 = radius: no round
 
813
        // corners, 0 = forward arrow: none, 0 = backward arrow: none
 
814
        fprintf(fd, "2 1 0 0 -1 %d 50 0 20 0.0 0 0 -1 0 0 %d\n",
 
815
                penColor, n);
 
816
        for (int i = 0 ; i < n ; i++ ) {
 
817
                fprintf(fd, "%.0f %.0f ",
 
818
                        Zoom(p[i].x * F), Zoom(p[i].y * F));
 
819
        }
 
820
        fprintf(fd, "\n");
 
821
}
 
822
 
 
823
 
 
824
/* virtual */ void FigGrafport::DrawSimplePolygon(const DPoint *p,
 
825
        int n)
 
826
{
 
827
        if (n < 2)
 
828
                return;
 
829
        int line_style;
 
830
        double style_val;
 
831
        switch ( GetLineStyle() ) {
 
832
        case LineStyle::INVISIBLE:
 
833
                return;
 
834
        case LineStyle::DASHED:
 
835
                line_style = 1;
 
836
                style_val = 4.0;
 
837
                break;
 
838
        case LineStyle::DOTTED:
 
839
                line_style = 2;
 
840
                style_val = 1.0;
 
841
                break;
 
842
        case LineStyle::WIDE_DOTTED:
 
843
                line_style = 2;
 
844
                style_val = 2.0;
 
845
                break;
 
846
        default:
 
847
                line_style = 0;
 
848
                style_val = 0.0;
 
849
                break;
 
850
        }
 
851
        int sub_type = 1; // open polyline
 
852
        if ( p[0] == p[n - 1] )
 
853
                sub_type = 3; // closed polyline
 
854
        // 2 = type: polyline, 7 = fill colour: white, 0 = depth, 0 = pen style
 
855
        // (not used), -1 = area fill: none, 0 = join style: miter, 0 = cap
 
856
        // style: butt, -1 = radius: no round corners, 0 = forward arrow: none,
 
857
        // 0 = backward arrow: none
 
858
        fprintf(fd, "2 %d %d %d %d 7 0 0 -1 %.1f 0 0 -1 0 0 %d\n",
 
859
                sub_type, line_style, GetLineWidth(), penColor,
 
860
                style_val, n);
 
861
        for (int i = 0 ; i < n ; i++ ) {
 
862
                fprintf(fd, "%.0f %.0f ",
 
863
                        Zoom(p[i].x * F), Zoom(p[i].y * F));
 
864
        }
 
865
        fprintf(fd, "\n");
 
866
}
 
867
 
 
868
 
 
869
void FigGrafport::MakeFigString(string *str) {
 
870
        char buf[8];
 
871
        string newstr;
 
872
        for (unsigned i=0; i<str->length(); i++) {
 
873
                unsigned char c = (*str)[i];
 
874
                if (!isascii(c)) {
 
875
                        sprintf(buf, "\\%o", c);
 
876
                        newstr += buf;
 
877
                }
 
878
                else if (c == '\\') {
 
879
                        newstr.add(c);
 
880
                        newstr.add(c);
 
881
                }
 
882
                else
 
883
                        newstr.add(c);
 
884
        }
 
885
        newstr += "\\001";
 
886
        *str = newstr;
 
887
}
 
888
 
 
889
void FigGrafport::SetFillColor() {
 
890
        Color *color = LookupColor(GetForegroundColor());
 
891
        if (color)
 
892
                fillColor = (int)color->pixel;
 
893
        else
 
894
                fillColor = -1; // default.
 
895
}
 
896
 
 
897
void FigGrafport::GetFigStringSize(const char *str, double &ht, double &wd) {
 
898
        XCharStruct overall;
 
899
        int dir, asc, desc;
 
900
        int nchars = strlen(str);
 
901
        XTextExtents(GetFont()->GetXFontStruct(),
 
902
                (char *)str, nchars, &dir, &asc, &desc, &overall);
 
903
        ht = F * (overall.ascent + overall.descent);
 
904
        wd = F * overall.width;
 
905
}
 
906
 
 
907
void FigGrafport::SetPSFont() {
 
908
        XFont *f = GetFont();
 
909
        int fam = f->GetFamily();
 
910
        if (fam == XFont::HELVETICA)
 
911
                psFont = 16;
 
912
        else if (fam == XFont::TIMESROMAN)
 
913
                psFont = 0;
 
914
        else if (fam == XFont::COURIER)
 
915
                psFont = 12;
 
916
        else if (fam == XFont::NEWCENTURYSCHLBK)
 
917
                psFont = 24;
 
918
        else if (fam == XFont::SYMBOL) {
 
919
                psFont = 32;
 
920
                return;
 
921
        }
 
922
        if (f->IsItalic())
 
923
                psFont += 1;
 
924
        if (f->IsBold())
 
925
                psFont += 2;
 
926
}
 
927
 
 
928
void FigGrafport::SetTexFont() {
 
929
        XFont *f = GetFont();
 
930
        texFont = 1;
 
931
        if (f->IsBold())
 
932
                texFont += 1;
 
933
        if (f->IsItalic())
 
934
                texFont += 2;
 
935
        int fam = f->GetFamily();
 
936
        if (fam == XFont::COURIER)
 
937
                texFont = 5;
 
938
}