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