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