]> git.lyx.org Git - lyx.git/blob - src/Painter.C
John's Layout Tabular UI improvements and Martins fixes to clearing the
[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 const c = uppercase(s[i]);
228                         if (c != s[i]) {
229                                 lyxfont::XSetFont(display, gc, smallfont);
230                                 XDrawString(display, owner.getPixmap(), gc,
231                                             tmpx, y, &c, 1);
232                                 tmpx += lyxfont::XTextWidth(smallfont, &c, 1);
233                         } else {
234                                 lyxfont::XSetFont(display, gc, f);
235                                 XDrawString(display, owner.getPixmap(), gc,
236                                             tmpx, y, &c, 1);
237                                 tmpx += lyxfont::XTextWidth(f, &c, 1);
238                         }
239                 }
240         }
241
242         if (f.underbar() == LyXFont::ON) {
243                 underline(f, x, y, lyxfont::width(s, ls, f));
244         }
245         
246         return *this;
247 }
248
249
250 PainterBase & Painter::text(int x, int y, XChar2b const * s, int ls,
251                         LyXFont const & f)
252 {
253         GC gc = lyxColorHandler->getGCForeground(f.realColor());
254         if (f.realShape() != LyXFont::SMALLCAPS_SHAPE) {
255                 lyxfont::XSetFont(display, gc, f);
256                 XDrawString16(display, owner.getPixmap(), gc, x, y, s, ls);
257         } else {
258                 LyXFont smallfont(f);
259                 smallfont.decSize().decSize().setShape(LyXFont::UP_SHAPE);
260                 static XChar2b c;
261                 int tmpx = x;
262                 for (int i = 0; i < ls; ++i) {
263                         if (s[i].byte1)
264                                 c = s[i];
265                         else {
266                                 c.byte1 = s[i].byte1;
267                                 c.byte2 = uppercase(s[i].byte2);
268                         }
269                         if (c.byte2 != s[i].byte2) {
270                                 lyxfont::XSetFont(display, gc, smallfont);
271                                 XDrawString16(display, owner.getPixmap(), gc,
272                                               tmpx, y, &c, 1);
273                                 tmpx += lyxfont::XTextWidth16(smallfont, &c, 1);
274                         } else {
275                                 lyxfont::XSetFont(display, gc, f);
276                                 XDrawString16(display, owner.getPixmap(), gc,
277                                               tmpx, y, &c, 1);
278                                 tmpx += lyxfont::XTextWidth16(f, &c, 1);
279                         }
280                 }
281         }
282         
283         if (f.underbar() == LyXFont::ON) {
284                 underline(f, x, y, lyxfont::width(s, ls, f));
285         }
286         
287         return *this;
288 }
289
290
291 void Painter::underline(LyXFont const & f, int x, int y, int width)
292 {
293         int const below = max(lyxfont::maxDescent(f) / 2, 2);
294         int const height = max((lyxfont::maxDescent(f) / 4) - 1, 1);
295         if (height < 2)
296                 line(x, y + below, x + width, y + below, f.color());
297         else
298                 fillRectangle(x, y + below, width, below + height,
299                               f.color());
300 }