]> git.lyx.org Git - lyx.git/blob - src/Painter.C
603ac4e6ed75e5b505e4120bafe65a61e71d90f9
[lyx.git] / src / Painter.C
1 // -*- C++ -*-
2 /* This file is part of
3  * ======================================================
4  * 
5  *           LyX, The Document Processor
6  *       
7  *          Copyright 1998-2000 The LyX Team
8  *
9  *======================================================*/
10
11 #include <config.h>
12
13 #ifdef __GNUG__
14 #pragma implementation
15 #endif
16
17 #ifdef USE_STL_MEMORY
18 #include <memory>
19 #endif
20
21 #include <cmath>
22
23 #include FORMS_H_LOCATION
24 #include "Painter.h"
25 #include "LString.h"
26 #include "debug.h"
27 #include "lyxfont.h"
28 #include "support/LAssert.h"
29 #include "support/lstrings.h"
30 #include "WorkArea.h"
31 #include "font.h"
32 #include "ColorHandler.h"
33
34 using std::endl;
35 using std::max;
36
37 Painter::Painter(WorkArea & wa)
38         : PainterBase(wa)
39 {
40         display = fl_display;
41 }
42
43
44 /* Basic drawing routines */
45
46 extern bool Lgb_bug_find_hack;
47
48 PainterBase & Painter::point(int x, int y, LColor::color c)
49 {
50         if (lyxerr.debugging()) {
51                 if (!Lgb_bug_find_hack)
52                         lyxerr << "point not called from "
53                                 "workarea::workhandler\n";
54                 lyxerr.debug() << "Painter drawable: "
55                                << owner.getPixmap() << endl;
56         }
57         
58         XDrawPoint(display, owner.getPixmap(),
59                    lyxColorHandler->getGCForeground(c), x, y);
60         return *this;
61 }
62
63
64 PainterBase & Painter::line(int x1, int y1, int x2, int y2,
65                         LColor::color col,
66                         enum line_style ls,
67                         enum line_width lw)
68 {
69         if (lyxerr.debugging()) {
70                 if (!Lgb_bug_find_hack)
71                         lyxerr << "line not called from "
72                                 "workarea::workhandler\n";
73                 lyxerr.debug() << "Painter drawable: "
74                                << owner.getPixmap() << endl;
75         }
76         
77         XDrawLine(display, owner.getPixmap(), 
78                   lyxColorHandler->getGCLinepars(ls, lw, col),
79                   x1, y1, x2, y2);
80         return *this;
81 }
82
83
84 PainterBase & Painter::lines(int const * xp, int const * yp, int np,
85                              LColor::color col,
86                              enum line_style ls,
87                              enum line_width lw)
88 {
89         if (lyxerr.debugging()) {
90                 if (!Lgb_bug_find_hack)
91                         lyxerr << "lines not called from "
92                                 "workarea::workhandler\n";
93                 lyxerr.debug() << "Painter drawable: "
94                                << owner.getPixmap() << endl;
95         }
96         
97 #ifndef HAVE_AUTO_PTR
98         XPoint * points = new XPoint[np];
99 #else
100         auto_ptr<XPoint> points(new Xpoint[np]);
101 #endif
102         for (int i = 0; i < np; ++i) {
103                 points[i].x = xp[i];
104                 points[i].y = yp[i];
105         }
106
107         XDrawLines(display, owner.getPixmap(),
108                    lyxColorHandler->getGCLinepars(ls, lw, col), 
109                    points, np, CoordModeOrigin);
110
111 #ifndef HAVE_AUTO_PTR
112         delete[] points;
113 #endif  
114         return *this;
115 }      
116
117
118 PainterBase & Painter::rectangle(int x, int y, int w, int h,
119                                  LColor::color col,
120                                  enum line_style ls,
121                                  enum line_width lw)
122 {
123         if (lyxerr.debugging()) {
124                 if (!Lgb_bug_find_hack)
125                         lyxerr << "rectangle not called from "
126                                 "workarea::workhandler\n";
127                 lyxerr << "Painter drawable: "
128                        << owner.getPixmap() << endl;
129         }
130         
131         XDrawRectangle(display, owner.getPixmap(),
132                        lyxColorHandler->getGCLinepars(ls, lw, col), 
133                        x, y, w, h);
134         return *this;
135 }
136
137
138 PainterBase & Painter::fillRectangle(int x, int y, int w, int h,
139                                  LColor::color col)
140 {
141         if (lyxerr.debugging()) {
142                 if (!Lgb_bug_find_hack)
143                         lyxerr << "fillrectangle not called from "
144                                 "workarea::workhandler\n";
145                 lyxerr << "Painter drawable: "
146                        << owner.getPixmap() << endl;
147         }
148         
149         XFillRectangle(display, owner.getPixmap(),
150                        lyxColorHandler->getGCForeground(col), x, y, w, h);
151         return *this;
152 }
153
154
155 PainterBase & Painter::fillPolygon(int const * xp, int const * yp, int np,
156                                LColor::color col)
157 {
158         if (lyxerr.debugging()) {
159                 if (!Lgb_bug_find_hack)
160                         lyxerr <<"fillpolygon not called from "
161                                 "workarea::workhandler\n";
162                 lyxerr << "Painter drawable: " << owner.getPixmap() << endl;
163         }
164         
165 #ifndef HAVE_AUTO_PTR
166         XPoint * points = new XPoint[np];
167 #else
168         auto_ptr<XPoint> points(new XPoint[np]);
169 #endif
170         for (int i=0; i < np; ++i) {
171                 points[i].x = xp[i];
172                 points[i].y = yp[i];
173         }
174
175         XFillPolygon(display, owner.getPixmap(),
176                      lyxColorHandler->getGCForeground(col), points, np, 
177                      Nonconvex, CoordModeOrigin);
178 #ifndef HAVE_AUTO_PTR
179         delete[] points;
180 #endif  
181         return *this;
182 }      
183
184
185 PainterBase & Painter::arc(int x, int y,
186                   unsigned int w, unsigned int h,
187                   int a1, int a2, LColor::color col)
188 {
189         if (lyxerr.debugging()) {
190                 if (!Lgb_bug_find_hack)
191                         lyxerr << "arc not called from "
192                                 "workarea::workhandler\n";
193                 lyxerr << "Painter drawable: " << owner.getPixmap() << endl;
194         }
195         
196         XDrawArc(display, owner.getPixmap(),
197                  lyxColorHandler->getGCForeground(col),
198                  x, y, w, h, a1, a2);
199         return *this;
200 }     
201
202
203 /// Draw lines from x1,y1 to x2,y2. They are arrays
204 PainterBase & Painter::segments(int const * x1, int const * y1, 
205                             int const * x2, int const * y2, int ns,
206                             LColor::color col,
207                             enum line_style ls, enum line_width lw)
208 {
209         if (lyxerr.debugging()) {
210                 if (!Lgb_bug_find_hack)
211                         lyxerr << "segments not called from "
212                                 "workarea::workhandler\n";
213                 lyxerr << "Painter drawable: " << owner.getPixmap() << endl;
214         }
215         
216 #ifndef HAVE_AUTO_PTR
217         XSegment * s= new XSegment[ns];
218 #else
219         auto_ptr<XSegment> s(new XSegment[ns]);
220 #endif
221         for (int i=0; i<ns; ++i) {
222                 s[i].x1 = x1[i];
223                 s[i].y1 = y1[i];
224                 s[i].x2 = x2[i];
225                 s[i].y2 = y2[i];
226         }
227         XDrawSegments(display, owner.getPixmap(),
228                       lyxColorHandler->getGCLinepars(ls, lw, col), s, ns);
229
230 #ifndef HAVE_AUTO_PTR
231         delete [] s;
232 #endif
233         return *this;
234 }
235
236
237 PainterBase & Painter::pixmap(int x, int y, int w, int h, Pixmap bitmap)
238 {
239         if (lyxerr.debugging()) {
240                 if (!Lgb_bug_find_hack)
241                         lyxerr << "workAreaExpose not called from "
242                                 "workarea::workhandler\n";
243                 lyxerr << "Painter drawable: " << owner.getPixmap() << endl;
244         }
245         
246         XGCValues val;
247         val.function = GXcopy;
248         GC gc = XCreateGC(display, owner.getPixmap(),
249                           GCFunction, &val);
250         XCopyArea(display, bitmap, owner.getPixmap(), gc,
251                   0, 0, w, h, x, y);
252         XFreeGC(display, gc);
253         return *this;
254 }
255
256
257 PainterBase & Painter::text(int x, int y, string const & s, LyXFont const & f)
258 {
259         return text(x, y, s.c_str(), s.length(), f);
260 }
261
262
263 PainterBase & Painter::text(int x, int y, char c, LyXFont const & f)
264 {
265         char s[2] = { c, '\0' };
266         return text(x, y, s, 1, f);
267 }
268
269
270 PainterBase & Painter::text(int x, int y, char const * s, int ls,
271                         LyXFont const & f)
272 {
273         if (lyxerr.debugging()) {
274                 if (!Lgb_bug_find_hack)
275                         lyxerr << "text not called from "
276                                 "workarea::workhandler\n";
277                 lyxerr << "Painter drawable: " << owner.getPixmap() << endl;
278         }
279         GC gc = lyxColorHandler->getGCForeground(f.realColor());
280         if (f.realShape() != LyXFont::SMALLCAPS_SHAPE) {
281                 lyxfont::XSetFont(display, gc, f);
282                 XDrawString(display, owner.getPixmap(), gc, x, y, s, ls);
283         } else {
284                 LyXFont smallfont(f);
285                 smallfont.decSize().decSize().setShape(LyXFont::UP_SHAPE);
286                 char c;
287                 int tmpx = x;
288                 for(int i = 0; i < ls; ++i) {
289                         c = s[i];
290                         if (islower(static_cast<unsigned char>(c))) {
291                                 c = toupper(c);
292                                 lyxfont::XSetFont(display, gc, smallfont);
293                                 XDrawString(display, owner.getPixmap(),
294                                             gc, tmpx, y, &c, 1);
295                                 tmpx += lyxfont::XTextWidth(smallfont, &c, 1);
296                                 //tmpx += lyxfont::width(c, f);
297                         } else {
298                                 lyxfont::XSetFont(display, gc, f);
299                                 XDrawString(display, owner.getPixmap(),
300                                             gc, tmpx, y, &c, 1);
301                                 tmpx += lyxfont::XTextWidth(f, &c, 1);
302                                 //tmpx += lyxfont::width(c, f);
303                         }
304                 }
305         }
306         underline(f, x, y, lyxfont::width(s, ls, f));
307         return *this;
308 }
309
310
311 void Painter::underline(LyXFont const & f, int x, int y, int width)
312 {
313         // What about underbars?
314         if (f.underbar() == LyXFont::ON && f.latex() != LyXFont::ON) {
315                 int below = max(lyxfont::maxDescent(f) / 2, 2);
316                 int height = max((lyxfont::maxDescent(f) / 4) - 1, 1);
317                 if (height < 2)
318                         line(x, y + below, x + width, y + below, f.color());
319                 else
320                         fillRectangle(x, y + below, width, below + height,
321                                       f.color());
322         }
323 }