]> git.lyx.org Git - lyx.git/blob - src/Painter.C
The graphics inset now has:
[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 "graphics/GraphicsImage.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,
175                             grfx::GImage const & image)
176 {
177         return pixmap(x, y, w, h, image.getPixmap());
178 }
179
180
181 PainterBase & Painter::text(int x, int y, string const & s, LyXFont const & f)
182 {
183         return text(x, y, s.data(), s.length(), f);
184 }
185
186
187 PainterBase & Painter::text(int x, int y, char c, LyXFont const & f)
188 {
189         char s[2] = { c, '\0' };
190         return text(x, y, s, 1, f);
191 }
192
193
194 PainterBase & Painter::text(int x, int y, char const * s, size_t ls,
195                         LyXFont const & f)
196 {
197         if (lyxrc.font_norm_type == LyXRC::ISO_10646_1) {
198                 boost::scoped_array<XChar2b> xs(new XChar2b[ls]);
199                 Encoding const * encoding = f.language()->encoding();
200                 LyXFont font(f);
201                 if (f.isSymbolFont()) {
202 #ifdef USE_UNICODE_FOR_SYMBOLS
203                         font.setFamily(LyXFont::ROMAN_FAMILY);
204                         font.setShape(LyXFont::UP_SHAPE);
205 #endif
206                         encoding = encodings.symbol_encoding();
207                 }
208                 for (size_t i = 0; i < ls; ++i) {
209                         Uchar c = encoding->ucs(s[i]);
210                         xs[i].byte1 = c >> 8;
211                         xs[i].byte2 = c & 0xff;
212                 }
213                 text(x , y, xs.get(), ls, font);
214                 return *this;
215         }
216
217         GC gc = lyxColorHandler->getGCForeground(f.realColor());
218         if (f.realShape() != LyXFont::SMALLCAPS_SHAPE) {
219                 lyxfont::XSetFont(display, gc, f);
220                 XDrawString(display, owner.getPixmap(), gc, x, y, s, ls);
221         } else {
222                 LyXFont smallfont(f);
223                 smallfont.decSize().decSize().setShape(LyXFont::UP_SHAPE);
224                 int tmpx = x;
225                 for (size_t i = 0; i < ls; ++i) {
226                         char const c = uppercase(s[i]);
227                         if (c != s[i]) {
228                                 lyxfont::XSetFont(display, gc, smallfont);
229                                 XDrawString(display, owner.getPixmap(), gc,
230                                             tmpx, y, &c, 1);
231                                 tmpx += lyxfont::XTextWidth(smallfont, &c, 1);
232                         } else {
233                                 lyxfont::XSetFont(display, gc, f);
234                                 XDrawString(display, owner.getPixmap(), gc,
235                                             tmpx, y, &c, 1);
236                                 tmpx += lyxfont::XTextWidth(f, &c, 1);
237                         }
238                 }
239         }
240
241         if (f.underbar() == LyXFont::ON) {
242                 underline(f, x, y, lyxfont::width(s, ls, f));
243         }
244         
245         return *this;
246 }
247
248
249 PainterBase & Painter::text(int x, int y, XChar2b const * s, int ls,
250                         LyXFont const & f)
251 {
252         GC gc = lyxColorHandler->getGCForeground(f.realColor());
253         if (f.realShape() != LyXFont::SMALLCAPS_SHAPE) {
254                 lyxfont::XSetFont(display, gc, f);
255                 XDrawString16(display, owner.getPixmap(), gc, x, y, s, ls);
256         } else {
257                 LyXFont smallfont(f);
258                 smallfont.decSize().decSize().setShape(LyXFont::UP_SHAPE);
259                 static XChar2b c;
260                 int tmpx = x;
261                 for (int i = 0; i < ls; ++i) {
262                         if (s[i].byte1)
263                                 c = s[i];
264                         else {
265                                 c.byte1 = s[i].byte1;
266                                 c.byte2 = uppercase(s[i].byte2);
267                         }
268                         if (c.byte2 != s[i].byte2) {
269                                 lyxfont::XSetFont(display, gc, smallfont);
270                                 XDrawString16(display, owner.getPixmap(), gc,
271                                               tmpx, y, &c, 1);
272                                 tmpx += lyxfont::XTextWidth16(smallfont, &c, 1);
273                         } else {
274                                 lyxfont::XSetFont(display, gc, f);
275                                 XDrawString16(display, owner.getPixmap(), gc,
276                                               tmpx, y, &c, 1);
277                                 tmpx += lyxfont::XTextWidth16(f, &c, 1);
278                         }
279                 }
280         }
281         
282         if (f.underbar() == LyXFont::ON) {
283                 underline(f, x, y, lyxfont::width(s, ls, f));
284         }
285         
286         return *this;
287 }
288
289
290 void Painter::underline(LyXFont const & f, int x, int y, int width)
291 {
292         int const below = max(lyxfont::maxDescent(f) / 2, 2);
293         int const height = max((lyxfont::maxDescent(f) / 4) - 1, 1);
294         if (height < 2)
295                 line(x, y + below, x + width, y + below, f.color());
296         else
297                 fillRectangle(x, y + below, width, below + height,
298                               f.color());
299 }