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