1
////////////////////////////////////////////////////////////////////////////////
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).
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.
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.
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
21
////////////////////////////////////////////////////////////////////////////////
23
#include "application.h"
26
#define square(x) ((x)*(x))
27
#define round(x) ((int)((x)+0.5))
29
Grafport::Grafport() {
31
int f = XFont::HELVETICA;
34
string foundry = "Adobe";
35
defaultFont = new XFont(&foundry, f, s, p, False);
37
backgroundColor = "white";
38
foregroundColor = "black";
40
lineStyle = LineStyle::SOLID;
41
fillStyle = FillStyle::UNFILLED;
42
colors = new List<Color *>;
45
Grafport::~Grafport () {
51
void Grafport::InitColors() {
52
List<Color *> *appColors = theApplication->GetColors();
53
for (appColors->first(); !appColors->done(); appColors->next()) {
54
Color *color = new Color(*appColors->cur());
56
color->allocated = False;
61
unsigned Grafport::CursorPosition(double x, double y,
62
const string *str, double hit_x, double hit_y)
64
int j = 0; // index in string.
65
unsigned n = 1; // number of lines processed.
66
unsigned nLines = str->lines();
67
// the cursor position, closest to hit_x, hit_y.
69
int fontHeight = font->GetHeight();
70
double offset = y - (nLines) * fontHeight/2;
72
const char *s = str->getstr();
73
// string is non-zero.
78
if (c == '\n' || c == '\r' || c == '\0') {
80
double y1 = offset + (n-1) * fontHeight;
81
double y2 = offset + n * fontHeight;
82
if (y1 <= hit_y && hit_y <= y2) {
83
// found right line, look at hit_x;
84
Point p1 = CursorPosition(x,y,&buf,0);
85
for (unsigned k = 1; k <= buf.length(); k++) {
86
Point p2 = CursorPosition(x,y,&buf,k);
87
int mid = (p1.x + p2.x)/2;
96
return min(cursor, str->length());
99
cursor += buf.length()+1;
100
buf = ""; // another line
105
return min(cursor, str->length());
108
Point Grafport::DrawStringsCentered(double x, double y, const string *str,
109
bool ul, int cursor) {
110
int j = 0; // index in string.
111
unsigned n = 1; // number of lines processed.
112
unsigned nLines = str->lines();
113
Point p = Point(static_cast<int>(0.5 + x),
114
static_cast<int>(0.5 + y)); // cursor position.
115
int fontHeight = font->GetHeight();
116
double offset = y - (nLines-1) * fontHeight/2;
118
const char *s = str->getstr();
119
// string is non-zero.
120
while (n <= nLines) {
124
if (c == '\n' || c == '\r' || c == '\0') {
126
// draw string in buf
127
y = offset + (n-1) * fontHeight;
129
DrawStringCenteredUnderlined(x, y, buf.getstr());
131
DrawStringCentered(x, y, buf.getstr());
132
// look for cursor position.
133
if (cursor <= j && cursor >= (int)(j - buf.length()))
134
p = CursorPosition(x, y, &buf,
135
cursor-j+buf.length());
136
buf = ""; // another line
144
Point Grafport::DrawStringsLeft(double topLeftx, double topLefty,
145
const string *str, bool ul, int cursor) {
146
int j = 0; // index in string.
147
unsigned n = 1; // number of lines processed.
148
unsigned nLines = str->lines();
149
topLefty += font->GetAscent();
150
Point p = Point(static_cast<int>(0.5 + topLeftx),
151
static_cast<int>(0.5 + topLefty)); // cursor position.
152
int fontHeight = font->GetHeight();
154
const char *s = str->getstr();
155
// string is non-zero.
156
while (n <= nLines) {
160
if (c == '\n' || c == '\r' || c == '\0') {
162
// draw string in buf
164
DrawStringLeftUnderlined(
165
topLeftx, topLefty, buf.getstr());
168
topLeftx, topLefty, buf.getstr());
169
// look for cursor position.
170
if (cursor <= j && cursor >= (int)(j - buf.length()))
172
topLeftx+font->StringWidth(&buf)/2,
173
topLefty-font->GetDescent(), &buf,
174
cursor-j+buf.length());
175
topLefty += fontHeight;
176
buf = ""; // another line
184
Point Grafport::DrawStringsRight(double topRightx, double topRighty,
185
const string *str, bool ul, int cursor) {
186
int j = 0; // index in string.
187
unsigned n = 1; // number of lines processed.
188
unsigned nLines = str->lines();
189
topRighty += font->GetAscent();
190
Point p = Point(static_cast<int>(0.5 + topRightx),
191
static_cast<int>(0.5 + topRighty)); // cursor position.
192
int fontHeight = font->GetHeight();
194
const char *s = str->getstr();
195
// string is non-zero.
196
while (n <= nLines) {
200
if (c == '\n' || c == '\r' || c == '\0') {
202
// int x = topRightx - font->StringWidth(&buf);
203
// draw string in buf
205
DrawStringRightUnderlined(
206
topRightx, topRighty, buf.getstr());
209
topRightx, topRighty, buf.getstr());
210
// look for cursor position.
211
if (cursor <= j && cursor >= (int)(j - buf.length()))
213
topRightx-font->StringWidth(&buf)/2,
214
topRighty-font->GetDescent(), &buf,
215
cursor-j+buf.length());
216
topRighty += fontHeight;
217
buf = ""; // another line
225
Point Grafport::CursorPosition(double x, double y, const string *text, int cursor) {
227
for(int i=0; i<cursor; i++)
229
int width = font->StringWidth(&str);
230
int base = font->GetHeight()/2 - font->GetDescent();
232
if (font->IsScalable())
233
str_x = x - font->StringWidth(text)/2 + width;
235
str_x = x - ZoomCorrect(font->StringWidth(text)/2 - width);
236
return Point(static_cast<int>(0.5 + str_x),
237
static_cast<int>(0.5 + y+base));
241
void Grafport::DrawRectangles(const Rectangle *rects, int n){
242
for (int i=0; i<n; i++)
243
DrawRectangle(rects[i].x,rects[i].y,
244
rects[i].width,rects[i].height);
248
void Grafport::FillRectangles(const Rectangle *rects, int n){
249
for (int i=0; i<n; i++)
250
FillRectangle(rects[i].x,rects[i].y,
251
rects[i].width,rects[i].height);
255
Color *Grafport::LookupColor(const string *colorName) {
256
for (colors->first(); !colors->done(); colors->next()) {
257
Color *color = colors->cur();
258
if (color->name %= *colorName)
264
Color *Grafport::LookupColor(const char *colorName) {
265
string x = colorName;
266
return LookupColor(&x);
269
void Grafport::AddColor(Color *c) {
270
colors->add(new Color(*c));
273
void Grafport::AddColor(const string *name, unsigned long pixel) {
274
Color *color = new Color(*name, pixel);
278
void Grafport::AddColor(const char *name, unsigned long pixel) {
284
void Grafport::RecalcPolygon(const Point *points, int nrPoints, Point *newPoints, int d) {
285
// it is a regular polygon.
286
Point p0 = points[0];
288
if (nrPoints % 2 == 0)
289
pN = points[nrPoints/2];
291
Point pN1 = points[nrPoints/2];
292
Point pN2 = points[1+nrPoints/2];
293
pN.x = (pN1.x + pN2.x) / 2;
294
pN.y = (pN1.y + pN2.y) / 2;
297
pM.x = (p0.x + pN.x) / 2;
298
pM.y = (p0.y + pN.y) / 2;
299
for (int i = 0; i < nrPoints; i++) {
314
void Grafport::DrawArc(double x, double y, double w, double h,
317
if ( GetLineStyle() != LineStyle::DUAL ) {
318
DrawSimpleArc(x, y, w, h, arc1, arc2);
321
double delta = ZoomCorrect(GetLineWidth());
322
double delta2 = 2.0 * delta;
323
DrawSimpleArc(x - delta, y - delta, w + delta2, h + delta2,
325
if ( w > delta2 && h > delta2 )
326
DrawSimpleArc(x + delta, y + delta,
327
w - delta2, h - delta2, arc1, arc2);
331
void Grafport::DrawLine(double x1, double y1,
332
double x2, double y2)
339
DrawOpenPolygon(points, 2);
343
static void RecalcPolygon(const DPoint *points, DPoint *right,
344
DPoint *left, double delta, int n)
349
bool closed = points[0] == points[n];
350
double dx1 = points[1].x - points[0].x;
351
double dy1 = points[1].y - points[0].y;
352
double d1 = ! dx1 && ! dy1 ? 0.0
353
: delta / sqrt(square(dx1) + square(dy1));
355
right[0].x = points[0].x - dy1 * d1;
356
left[0].x = points[0].x + dy1 * d1;
357
right[0].y = points[0].y + dx1 * d1;
358
left[0].y = points[0].y - dx1 * d1;
362
right[i].x = points[i].x - dy1 * d1;
363
left[i].x = points[i].x + dy1 * d1;
364
right[i].y = points[i].y + dx1 * d1;
365
left[i].y = points[i].y - dx1 * d1;
370
dx2 = points[1].x - points[0].x;
371
dy2 = points[1].y - points[0].y;
373
dx2 = points[i+1].x - points[i].x;
374
dy2 = points[i+1].y - points[i].y;
376
double d2 = ! dx2 && ! dy2 ? 0.0
377
: delta / sqrt(square(dx2) + square(dy2));
381
double det = dx1 * dy2 - dx2 * dy1;
383
double b1 = dy2 * d2 - dy1 * d1;
384
double b2 = dx1 * d1 - dx2 * d2;
385
double t = (b1 * dy2 - b2 * dx2) / det;
386
right[i].x -= dx1 * t;
387
left[i].x += dx1 * t;
388
right[i].y -= dy1 * t;
389
left[i].y += dy1 * t;
404
void Grafport::DrawOpenPolygon(const DPoint *points, int n) {
407
if ( GetLineStyle() != LineStyle::DUAL) {
408
DrawSimplePolygon(points, n);
411
DPoint *p1 = new DPoint[n], *p2 = new DPoint[n];
412
::RecalcPolygon(points, p1, p2, ZoomCorrect(GetLineWidth()), n);
413
DrawSimplePolygon(p1, n);
414
DrawSimplePolygon(p2, n);
420
void Grafport::DrawCurve(const DPoint *p)
422
if ( GetLineStyle() != LineStyle::DUAL) {
427
::RecalcPolygon(p, p1, p2, ZoomCorrect(GetLineWidth()), 4);
433
// This function is incorrect because it assumes that DrawSimpleCurve draws
434
// a spline that contains points[0], points[1], points[2] and points[3].
435
///* virtual */ void Grafport::DrawSimpleArc(
436
// double x, double y,
437
// double w, double h, int arc1, int arc2)
444
// double a1 = arc1 * (PI / 180);
445
// double a2 = arc2 * (PI / 180);
446
// points[0].Set(x + w * cos(a1), y - h * sin(a1));
447
// points[1].Set(x + w * cos((a1 * 2.0 + a2) / 3.0),
448
// y - h * sin((a1 * 2.0 + a2) / 3.0));
449
// points[2].Set(x + w * cos((a1 + a2 * 2.0) / 3.0),
450
// y - h * sin(a1 + a2 * 2.0) / 3.0));
451
// points[3].Set(x + w * cos(a2), y - h * sin(a2));
452
// DrawSimpleCurve(points);